URL'deki noktalar ASP.NET mvc ve IIS ile 404'e neden oluyor


303

URL'lerimin yolda noktalar olmasını gerektiren bir projem var. Örneğin, www.example.com/people/michael.phelps gibi bir URL’m olabilir

Noktalı URL'ler 404 oluşturur. Yönlendirmem iyi. Eğer nokta olmadan michaelphelps'i geçersem, o zaman her şey işe yarar. Nokta eklersem 404 hatası alıyorum. Örnek site, Windows 7'de IIS8 Express ile çalışıyor. URLScan çalışmıyor.

Benim web.config için aşağıdaki eklemeyi denedim:

<security>
  <requestFiltering allowDoubleEscaping="true"/>
</security>

Ne yazık ki bu bir fark yaratmadı. Sadece 404.0 Bulunamadı hatası alıyorum.

Bu bir MVC4 projesi ama bunun önemli olduğunu düşünmüyorum. Yönlendirmem iyi çalışıyor ve bir nokta içerene kadar beklediğim parametreler var.

URL'mde noktalar olabilmesi için ne yapılandırmam gerekiyor?


93
Buna çok zaman harcadığım inanamıyorum. Sondaki eğik çizgi eklersem URL iyi çalışır. Örneğin, www.example.com/people/michael.phelps/ ancak eğik çizgi olmadan IIS 404 hatası verir.
Mark

15
Mark - bunun nedeni, eğik çizgi olmadan IIS'nin gitmesi ve bulması gereken bir dosya olduğunu düşünmesidir. Eğik çizgi eklemenin etkisi ... bu gerçek bir dosya değil. Ayrıca, aşağıdaki yapılandırma seçeneği IIS'ye bir dosya değilse, bunun yerine yönlendirmeyi denediğini bildirir.
Tommy

Projemi mvc 4 + asp.net 4.5'e güncelledikten sonra aynı sorunu yaşıyorum.
Tadeu Maia

Etrafında bir çalışma olarak, URL'leri sonuna eğik çizgi eklemek için IIS Yeniden Yazmayı kullanıyorum.
Mark

4
Bu benim için işe yaramıyor. URL, "." İle iyi çalışıyor. ancak en sonunda olduğunda bir hata veriyor
Arcadian

Yanıtlar:


379

Bu çalışmayı sitemin HTTP işleyicilerini düzenleyerek aldım. İhtiyacım için bu iyi çalışıyor ve sorunumu çözüyor.

Sadece belirli yol ölçütlerini arayan yeni bir HTTP işleyicisi ekledim. İstek eşleşirse, işleme için doğru şekilde .NET'e gönderilir. URLRewrite kesmek veya RAMMFAR etkinleştirmek bu çözüm ile çok mutluyum.

Örneğin, .NET'in www.example.com/people/michael.phelps URL'sini işlemesini sağlamak için, öğenizin içindeki sitenizin web.config dosyasına aşağıdaki satırı ekleyin system.webServer / handlers:

<add name="ApiURIs-ISAPI-Integrated-4.0"
     path="/people/*"
     verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

Düzenle

Bu sorunun çözümü ileri süren diğer bir konu bulunmuyor RAMMFARya RunAllManagedModulesForAllRequests. Bu seçeneğin etkinleştirilmesi, tüm istekler için yönetilen tüm modülleri etkinleştirir. Bu, resimler, PDF'ler ve diğer her şey gibi statik dosyaların gerekmediğinde .NET tarafından işleneceği anlamına gelir. Bu seçenekler, belirli bir vakanız yoksa en iyi şekilde bırakılır.


3
İşte tam bir örnek stackoverflow.com/a/16607685/801189 Bu cevaba dayanarak
VB

10
bunu [path = "*"] ile ekledikten sonra .css, .js gibi statik dosyalara yapılan tüm istekler başarısız olur. Bu " domain / ABCDE.FGHIJ " gibi görünen URL'leri işleyen özel bir yol var . Tüm statik dosyalarım / Content dizinimde. Tüm dizini bundan hariç tutmanın bir yolu var mı? RAMMFAR'ı gerçek işlere ayarlamak ama bu yükü önlemek istiyorum.
Lamarant

2
Yerel IIS, eğik çizgi ile çalışır, ancak IIS8 yalnızca ilk eğik çizgi olmadan rotayı anlar.
Pavel Voronin

2
@Lamarant ile aynı sorunu yaşıyorum ... Bu statik dosyaları engeller. Neden biliyor musun? Burada MVC4 kullanıyor.
eestein

3
MVC5'te çalışır, ancak yolun başına eğik çizgi koyarsanız, yalnızca yol ana bilgisayar adından hemen sonra olduğunda çalışır (uygulama klasörüne göreli değildir). Örneğin path / people / *, www.example.com/people/michael.phelps için çalışır, ancak www.example.com/app/people/michael.phelps için çalışmaz. AFAIK uygulaması göre yolu yapmak için bir yolu yoktur.
Hogan

46

Etrafta bazı alay sonra relaxedUrlToFileSystemMapping benim için hiç işe yaramadı, benim durumumda çalıştı RAMMFAR doğru olarak ayarlamak, aynı (.net 4.0 + mvc3) ve (.net 4.5 + mvc4) için geçerlidir.

<system.webserver>
    <modules runAllManagedModulesForAllRequests="true">

RAMMFAR ve performans hakkında RAMMFAR gerçek Hanselman gönderisini ayarlarken dikkat edin


5
RAMMFAR'ı ayarlarken dikkat edin ... Bu <modülleri kullanırsam herhangi bir performans kaybı var mı runAllManagedModulesForAllRequests = "true">
Shanker Paudel

1
Orijinal poster durumunda, IIS7 ve üstü kullandığından buna gerek yoktur. Orada varsayılan ve RAMMFAR ayarı gerçekten exta maliyeti. Bkz. Msdn.microsoft.com/en-us/library/…
Richard

Bu yararlı olsa da, bu benim için MVC5 / IIS7'de 404'leri döndürmeyi durdurmak için dönemler almak için yeterli değildi.
Chris Moschini

Bu seçeneği açık
tutmaktan

Mümkünse bunu canlı bir sitede yapmayın.
NickG

27

Web.config dosyasında relaxedUrlToFileSystemMapping özelliğini ayarlamanız gerektiğine inanıyorum. Haack bir süre önce bu konuda bir makale yazdı (ve aynı tür soruları soran başka SO yayınları da var )

<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />

Düzenle Aşağıdaki yorumlardan, .NET / IIS'nin sonraki sürümlerinde bunun system.WebServeröğede yer alması gerekebilir .

<system.webServer>
<httpRuntime relaxedUrlToFileSystemMapping="true" />

2
Bu mvc3 + .net4.0 ile vardı ve güzel çalıştı, ama artık mvc4 + .net4.5 ile çalışmıyor.
Tadeu Maia

4
RelaxedUrlToFileSystemMapping'i başarılı olmadan denedim. MVC'nin en yeni sürümleriyle çalıştığını sanmıyorum.
Mark

Bu, url /WEB-INF./web.xml dosyasını yakalamama ve denediğim birçok yol çalışmadığında özel bir hata sayfasına yönlendirmeme izin verdi.
quentin-starin

3
İlginç. Sizin için işe yaramadığı göz önüne alındığında, bunun benim için işe yaramayacağını varsaymak üzereydim ... .NET4.5 ile MVC4'te olduğum göz önüne alındığında. Ama tombala, yine de çalıştı. Benim durumumda, yalnızca "." son karakter olarak. 404'ler alıyordum ama bu sorunu düzeltti.
PandaWood

Güvenlik yansımaları var mı?
Paesano2000

23

Ben uzun süre boşuna tüm farklı çareleri takip bu konuda takılıp kaldım.

Noktaları [.] İçeren URL'nin sonuna eğik çizgi [/] eklerken 404 hatası atmadığını ve aslında işe yaradığını fark ettim.

Sonunda, belirli bir modeli izlemek ve eğik çizgiyi eklemek için IIS URL Yeniden Yazma gibi bir URL yeniden yazma aracını kullanarak sorunu çözdüm.

URL'm şuna benziyor: /Contact/~firstname.lastname bu yüzden kalıbım basitçe: /Contact/~(.*[^/ gelbe)$

Bu fikri Scott Forsyth'tan aldım, aşağıdaki bağlantıya bakın: http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path


Bu benim için çalıştı (MVC5). Yukarıdaki diğer öneriler işe yaramadı ve gerekli değildi, sadece sondaki eğik çizgi. @ Jonduncan05 önerdiği gibi benim güzergah değişecek burada .
markau

Teşekkürler, Leon. Günü benim için kurtardı. Tüm web.config hakkında emin değilim burada insanlar hakkında konuşmak şeyler, ama eklemek / son ihtiyacım cevap oldu. Benim durumumda, sunucu tarafı denetleyicisi ve onu çağıran javascript üzerinde kontrol var, bu yüzden sadece JavaScript ve voila güncelledim!
Frog Pr1nce

21

Bu bölümü Web.config dosyasına eklemeniz yeterlidir ve / {* pathInfo} yoluna yapılan tüm istekler, pathInfo'da noktalar olsa bile belirtilen işleyici tarafından işlenir. (ServiceStack MVC Host Web.config örneğinden alınmıştır ve bu cevap https://stackoverflow.com/a/12151501/801189 )

Bu hem IIS 6 hem de 7 için çalışmalıdır. 'Add' öğelerinde path = "*" değiştirerek 'route' işleminden sonra farklı yollara belirli işleyiciler atayabilirsiniz.

  <location path="route">
    <system.web>
      <httpHandlers>
        <add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
      </httpHandlers>
    </system.web>
    <!-- Required for IIS 7.0 -->
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true" />
      <validation validateIntegratedModeConfiguration="false" />
      <handlers>
        <add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
      </handlers>
    </system.webServer>
  </location>

2
RunAllManagedModulesForAllRequests (RAMMFAR) 'nin performans sonuçlarına dikkat edin. Bu, her istek için yönetilen tüm modülleri etkinleştirir. Görüntüler gibi statik dosyalar doğrudan IIS tarafından işlenebilir, ancak bu, her isteğe yük ekleyerek her modül aracılığıyla bunları işler.
Mark

@MarkS. Evet, ancak <location> bölümünü kullanırsak ve ana <system.webServer> bölümünde runAllManagedModulesForAllRequests ayarlamazsak, bu yalnızca rota / ... isteğini etkileyeceğine inanıyorum.
VB

@VB Ben sistemde .NET işlemek gerekiyordu bir URL eşleşen dosyaları yoksa, sadece işleyici yeterli olduğunu düşünüyorum. Bazı nedenlerden dolayı, RAMMFAR <location> seviyesinde çalışmadı, ancak işleyici çözümü işe yaradı.
webXL

@webXL <location>, MVC'nin belirtilen bir rota için istekleri işlemesini ve route.IgnoreRoute ("route / {* pathInfo}") eklemesini istemediğinizde gerekir; Ardından IIS, <location path = "route"> konum bölümüne bakar ve konum bölümünde belirtilen işleyicileri kullanır, ancak MVC'nin yönlendirme ve diğer MVC'nin boru hattı adımlarını tamamen atlar. Projemde, ServiceStack api bu kurulum olmadan çalışmıyor.
VB

Neden sadece işleyici eklemek işe yaramaz? Benim durumumda, işleyici ile birlikte RAMMFAR eklemem gerekiyor. Burada iyi bir açıklama arıyorum. :)
Aditya Patil

6

MVC 5.0 Geçici Çözümü.

Önerilen cevapların çoğu MVC 5.0'da işe yaramıyor gibi görünüyor.

Son bölümdeki 404 nokta sorunu, o bölümü bir eğik çizgi ile kapatarak çözülebildiğinden, işte kullandığım küçük hile, temiz ve basit.

Size uygun bir yer tutucu tutarken:

@Html.ActionLink("Change your Town", "Manage", "GeoData", new { id = User.Identity.Name }, null)

işi yapmak için biraz jquery / javascript ekleyin:

<script>
    $('a:contains("Change your Town")').on("click", function (event) {
        event.preventDefault();
        window.location.href = '@Url.Action("Manage", "GeoData", new { id = User.Identity.Name })' + "/";
    });</script>

lütfen değişen eğik çizgiye dikkat edin.

http://localhost:51003/GeoData/Manage/user@foo.com

içine

http://localhost:51003/GeoData/Manage/user@foo.com/

5

Sadece bir web sayfasında olanlar için süper kolay cevap. İşlem bağlantınızı ve sonunda bir + "/" işaretini düzenleyin.

  @Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |

Benim için çözdüm! Basit ve zarif! En rahatsız edici, geliştirme sırasında Windows 10'da '/' olmadan çalışmasıdır, ancak Windows 2012 için gerekli gibi görünmektedir.
On Brink'i

2

Noktalar yerine tire kullanmayı düşünmek isteyebilirsiniz.

Gelen Pro ASP MVC 3 Framework onlar dostu URL'ler yapma konusunda bu öneririz:

Sembollerden, kodlardan ve karakter dizilerinden kaçının. Sözcük ayırıcı istiyorsanız, tire işareti (/ my-great-article) kullanın. Alt çizgiler düşmanca ve URL kodlu alanlar tuhaf (/ benim + harika + makalem) veya iğrenç (/ benim% 20great% 20 parçacık).

URL'lerin insanlar için okunması ve değiştirilmesi kolay olması gerektiğinden de bahseder. Belki de nokta yerine tire kullanmayı düşünmenin bir nedeni de aynı kitaptan geliyor:

HTML sayfaları (.aspx veya .mvc) için dosya adı uzantıları kullanmayın, bunları özel dosya türleri (.jpg, .pdf, .zip, vb.) İçin kullanın. MIME türünü uygun şekilde ayarlarsanız web tarayıcıları dosya adı uzantılarını önemsemez, ancak insanlar yine de PDF dosyalarının .pdf ile bitmesini bekler

Bu nedenle, bir dönem insanlar için hala okunabilir olsa da (tirelardan daha az okunabilir olsa da, IMO), dönemden sonra ne olduğuna bağlı olarak yine de biraz kafa karıştırıcı / yanıltıcı olabilir. Birinin soyadının zip olması durumunda ne olur? Daha sonra URL, uygulamayı yazan geliştirici için bile yanıltıcı olabilecek / John-zip yerine /John.zip olacaktır.


Büyük olasılıkla doğal olarak noktalar içeren bir kullanıcı adı veya başka bir alandır. Bununla birlikte, StackOverflow tüm noktalama işaretlerini (dahil .) kullanıcı url'lerinde tire işareti ile değiştirir : P
jli

Açıkçası rota parametresinde dosya adları içeren güvenli dosya alma hizmeti var çünkü bu karşılaştım ...
FlavorScape

Açık bir nedenden ötürü reddedildi: Bu soruya cevap vermiyor. Yapabilseydim, URL'mde noktaların görünmesine izin vermezdim. URL oluşturulduğundan ve insanlar tarafından okunabilir olması gerektiğinden görünürler.
mg30rg

2

URI'nizi sorgu dizeleri olmadan tutmanızın ne kadar önemli olduğuna bağlı olarak, değeri URI yerine sorgu dizesinin bir parçası olarak noktalarla da iletebilirsiniz.

Örneğin, www.example.com/people?name=michael.phelps herhangi bir ayarı veya hiçbir şeyi değiştirmek zorunda kalmadan çalışır.

Temiz bir URI'ye sahip olmanın zerafetini kaybedersiniz, ancak bu çözüm herhangi bir ayar veya işleyici değiştirmeyi veya eklemeyi gerektirmez.


1

URL yapınızı değiştirmek mümkün müdür?
Üzerinde çalıştığım şey için

url: "Download/{fileName}"

ama a. olan herhangi bir şeyle başarısız oldu. içinde.

Güzergahı

    routes.MapRoute(
        name: "Download",
        url:  "{fileName}/Download",
        defaults: new { controller = "Home", action = "Download", }
    );

Şimdi koyabilirim localhost:xxxxx/File1.doc/Downloadve iyi çalışıyor.

Görünümdeki yardımcılarım da aldı

     @Html.ActionLink("click here", "Download", new { fileName = "File1.doc"})

bu da localhost:xxxxx/File1.doc/Downloadbiçime bir bağlantı oluşturur .

Belki rotanızın sonuna "/ view" veya işlem gibi gereksiz bir kelime koyabilirsiniz, böylece mülkünüz aşağıdaki /gibi bir şeyle sona erebilir/mike.smith/view


1

Yolu değiştirmek kadar basit = " ." to path = " ". Sadece web.config dosyasındaki ExensionlessUrlHandler-Integrated-4.0 yolundaki noktayı kaldırın.

İşte güzel bir makale https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application


Bu bağlantı beni sorunum için en iyi çözüme götürdü (segment bir "." Karakteri içeriyor, ancak istemciler "/" ile devam etmiyor). < "True" / = modülleri runAllManagedModulesForAllRequests> - <System.webServer> Web.config içinde bu satırı alarak Sabit
NickBeaugié

1

Yukarıdaki tüm çözümleri denedim ama hiçbiri benim için çalışmadı. Ne işe yaradı, tüm çok dilli sürümleri dahil olmak üzere .NET sürümleri> 4.5'i kaldırmaktı; Sonunda yeni (sadece İngilizce) sürümleri parça parça ekledim. Şu anda sistemime yüklenen sürümler:

  • 2.0
  • 3.0
  • 3,5 4
  • 4.5
  • 4.5.1
  • 4.5.2
  • 4.6
  • 4.6.1

Ve bu noktada hala çalışıyor. 4.6.2'yi yüklemekten korkuyorum çünkü her şeyi mahvedebilir.

Bu yüzden sadece 4.6.2 veya tüm İngilizce olmayan sürümlerin yapılandırmamı bozduğunu düşünebilirim.



0

Çözüm, sembol içermeyen bir biçime .base64 olarak kodlamayı da düşünebilir .

Js eklenmelidir

btoa(parameter); 

Denetleyicide

byte[] bytes = Convert.FromBase64String(parameter);
string parameter= Encoding.UTF8.GetString(bytes);

0

Web.config arşivine URL Yeniden Yazma kuralı ekleyin. Sen olmalı URL Yeniden Yazma modülünü zaten IIS yüklü. Aşağıdaki yeniden yazma kuralını kendiniz için ilham kaynağı olarak kullanın.

<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Add trailing slash for some URLs" stopProcessing="true">
        <match url="^(.*(\.).+[^\/])$" />
          <conditions>
              <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
              <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Redirect" url="{R:1}/" />
      </rule>
    </rules>
    </rewrite>
</system.webServer>

</configuration> 

0

Ayrıca, (ilgili) işleyici eşlemelerinizin sırasını kontrol edin. Sonra .svc (.fofo.asmx/bar.svc/path) ile bir .ashx vardı. .Svc eşlemesi ilk olarak .asmx'ten önce eşleşen .svc yolu için 404'tür. Çok fazla düşünmemiştim ama belki yolu kodlayan url bununla ilgilenirdi.


-3
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    [RoutePrefix("File")]
    [Route("{action=index}")]
    public class FileController : Controller
    {
        // GET: File
        public ActionResult Index()
        {
            return View();
        }

        [AllowAnonymous]
        [Route("Image/{extension?}/{filename}")]
        public ActionResult Image(string extension, string filename)
        {
            var dir = Server.MapPath("/app_data/images");

            var path = Path.Combine(dir, filename+"."+ (extension!=null?    extension:"jpg"));
           // var extension = filename.Substring(0,filename.LastIndexOf("."));

            return base.File(path, "image/jpeg");
        }
    }
}

1
Bu OP'nin sorusuna nasıl cevap veriyor? Lütfen açıklamak ister misiniz?
kayess

bu bir çözüm değildir, dosya uzantısının uri yoluna (nokta olmadan) yerleştirilmesini gerektiren bir saldırıdır, örneğin "/ app_data / images / cow / jpg" dosyasını almak için "~ / Image / jpg / cow" - - bu adam ve bu ihtiyacı bulan herkesin çözümü değil.
Shaun Wilson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.