Karakter titik '.' di MVC Web API 2 untuk permintaan seperti api / people / STAFF.45287

106

URL yang saya coba biarkan berfungsi adalah dengan gaya: http://somedomain.com/api/people/staff.33311 (seperti situs seperti LAST.FM mengizinkan semua jenis tanda di url RESTFul & WebPage mereka , misalnya " http://www.last.fm/artist/psy'aviah " adalah url valid untuk LAST.FM).

Apa yang berhasil adalah skenario berikut: - http://somedomain.com/api/people/ - yang mengembalikan semua orang - http://somedomain.com/api/people/staff33311 - akan berfungsi juga, tetapi bukan itu yang saya ' m setelah saya ingin url menerima "titik", seperti contoh di bawah - http://somedomain.com/api/people/staff.33311 - tetapi ini memberi saya

HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

Saya telah menyiapkan hal-hal berikut:

  1. Pengontrol "PeopleController"

    public IEnumerable<Person> GetAllPeople()
    {
        return _people;
    }
    
    public IHttpActionResult GetPerson(string id)
    {
        var person = _people.FirstOrDefault(p => p.Id.ToLower().Equals(id.ToLower()));
        if (person == null)
            return NotFound();
    
        return Ok(person);
    }    
  2. WebApiConfig.cs

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
    
        // Web API routes
        config.MapHttpAttributeRoutes();
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }

Saya sudah mencoba mengikuti semua tip dari posting blog ini http://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx tetapi masih tidak berfungsi .. Saya juga merasa ini cukup membosankan dan saya ingin tahu apakah tidak ada yang lain, cara yang lebih baik dan lebih aman.

Kami memiliki Id kami secara internal seperti ini, jadi kami harus menemukan solusi untuk menyesuaikan titik dengan satu atau lain cara, lebih disukai dalam gaya "." tapi saya terbuka untuk saran alternatif untuk url jika perlu ...

Yves Schelpe
sumber
10
Bukan jawaban, tapi mengapa Anda mendapatkan 404 untuk somedomain.com/api/people/staff.33311 - secara default, IIS melihat URL ini dan melihat. sebagai ekstensi file dan memanggil penangan file statis, melewati MVC API Anda. Jawaban yang Anda terima (menjalankan semua modul yang dikelola untuk semua permintaan) berfungsi karena Anda memaksa setiap permintaan ke IIS untuk melalui pipeline ASP.NET (oleh karena itu, pengontrol Anda)
Henry C
Posting terkait erat di sini .
NSP

Jawaban:

104

Pengaturan berikut di web.configfile Anda akan memperbaiki masalah Anda:

<configuration>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
Kiran Challa
sumber
4
Itu berhasil. Padahal, apakah ada kerentanan dengan mengatur opsi ini? Mengapa ini bukan perilaku standar?
Yves Schelpe
2
Oke, untuk kepentingan siapa pun: Saya melihat pertanyaan saya di atas dijawab di sini pada jawaban yang diterima pada saat penulisan (jawaban oleh Kapil Khandelwal): stackoverflow.com/questions/11048863/…
Yves Schelpe
2
Ya, berfungsi, bus yang lain, saya ingin tahu modul khusus mana yang diperlukan agar fungsi ini berfungsi?
Greg Z.
3
Ketika saya mencoba ini, itu hanya akan berhasil jika saya meletakkan '/' di ujung jalur. Ada saran mengapa demikian? Di samping catatan, jawaban di bawah ini yang secara khusus menambahkan 'UrlRoutingModule' alih-alih menjalankan semua modul, juga berfungsi untuk saya, meskipun masih dengan masalah yang membutuhkan '/' di bagian akhir untuk berfungsi.
Nikolaj Dam Larsen
10
stackoverflow.com/a/12151501/167018 layak untuk dilihat jika Anda khawatir (dan memang seharusnya demikian) tentang dampak kinerja dari pengaktifan runAllManagedModulesForAllRequests.
Henry C
140

Sufiks URL dengan garis miring misalnya, http://somedomain.com/api/people/staff.33311/bukan http://somedomain.com/api/people/staff.33311.

Danny Varod
sumber
3
@AgustinMeriles, jawaban saya dapat dianggap lebih sebagai solusi daripada jawaban sebenarnya, tergantung pada interpretasi Anda terhadap pertanyaan tersebut.
Danny Varod
5
Itu tidak berfungsi ketika titik berada di akhir bagian URL seperti di / orang / anggota.
eYe
2
Tidak, bagaimana jika saya tidak ingin tebasan di akhir ?! Ini seharusnya tidak diperlukan.
Josh M.
1
@Tokopedia Ini adalah solusi, saya tidak menulis ASP.NET. Selain itu, garis miring tidak memengaruhi permintaan. Memang, bagaimanapun, membantu membuat niat Anda lebih jelas seperti di google.com/my query goes here/vs google.com/subDomain my query goes here.
Danny Varod
1
Ya, ini yang terbaik, Anda tidak perlu memodifikasi web.config.
Timothy Gonzalez
35

Saya telah menemukan bahwa menambahkan yang berikut sebelum standar ExtensionlessUrlHandlermemecahkan masalah bagi saya:

<add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
     path="api/*"
     verb="*"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

Saya tidak berpikir nama sebenarnya terlalu penting kecuali mungkin membantu jika IDE Anda (Visual Studio dalam kasus saya) mengelola konfigurasi situs Anda.

H / T ke https://stackoverflow.com/a/15802305/264628

BrianS
sumber
Saya menambahkannya 'setelah' garis standar dan itu juga berfungsi dengan baik.
Jalal El-Shaer
Ini harus menjadi jawaban yang diterima. Tidak membutuhkan / di akhir uri
daudihus
2
Terima kasih untuk SEBELUMNYA, karena tidak berfungsi setelahnya!
Mese
Saya percaya modul berjalan dalam urutan deklarasi, jadi selalu letakkan yang lebih spesifik (atau lebih penting) sebelum yang lebih umum.
BrianS
24

Saya tidak tahu apa yang sebenarnya saya lakukan, tetapi setelah sedikit bermain dengan jawaban sebelumnya, saya menemukan solusi lain yang mungkin lebih tepat:

<system.webServer>
<modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</modules>
</system.webServer>
Greg Z.
sumber
Terima kasih, saya juga tidak tahu apa yang dilakukannya tetapi ini terlihat lebih baik daripada solusi lainnya.
Thomas
1
tampaknya memindahkan modul perutean url (yang menangkap bahwa permintaan tersebut menyertakan ekstensi dan kemudian mencoba menanganinya sebagai file) ke akhir daftar modul, yang cukup untuk meletakkannya setelah modul menangani permintaan api . IMHO, ini adalah solusi terbaik yang tersedia dari yang pernah saya lihat di SO, setidaknya ATTOW
James Manning
1
Ini bukanlah relokasi ke akhir daftar, ini adalah penghapusan prasyarat default yang hanya dijalankan modul ini untuk penangan terkelola. Konfigurasi default menggunakan format ini:<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler" />
theta-fish
Terima kasih - itu akan menjelaskan perilakunya.
Greg Z.
8

Saya menemukan bahwa saya perlu melakukan lebih dari sekadar menyetel runAllManagedModulesForAllRequestsatribut ke true. Saya juga harus memastikan bahwa penangan URL tanpa ekstensi telah dikonfigurasi untuk melihat semua jalur. Selain itu, ada satu lagi pengaturan konfigurasi bonus yang dapat Anda tambahkan yang akan membantu dalam beberapa kasus. Ini adalah Web.config saya:

<system.web>
    <httpRuntime relaxedUrlToFileSystemMapping="true" />
</system.web>
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
        <remove name="WebDAV" />
        <remove name="OPTIONSVerbHandler" />
        <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
        <add name="ExtensionlessUrlHandler-Integrated-4.0"  path="*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>

Catatan, khususnya, bahwa ExtensionlessUrlHandler-Integrated-4.0memiliki nya pathset atribut *sebagai lawan *.(misalnya).

Josh M.
sumber
Saya baru saja mendapat sedikit path="*.". Hanya penasaran, apa alasan orang mengaturnya path="*."?
JustinP8
Sebenarnya, saya mengubahnya menjadi path="*"dan mengalami masalah karena kami menghosting situs dokumentasi berdampingan dengan WebAPI kami dan situs tersebut memiliki masalah dengan .jpg, .png, dan file lain dengan ekstensi.
JustinP8
@ JustinP8 Apakah Anda juga mengatur <modules runAllManagedModulesForAllRequests="true" />? Itu harus membuat NET menangani file-file statis tersebut.
Josh M.
1
Iya. Saya akhirnya melakukan itu. Saya tidak terlalu suka itu karena sekarang semua file statis melalui pipa NET. Untungnya, karena ini adalah layanan webAPI, hanya item Swagger dan Swashbuckle untuk situs dokumen / pembantu API yang terpengaruh.
JustinP8
saya menemukan ini merusak semua permintaan file statis. error 500. Saya menjalankan runAllManaged ... disetel ke true.
Sam
2

Saya terjebak dalam situasi ini tetapi menambahkan / di akhir URL tidak terlihat bersih bagi saya.

jadi tambahkan saja di bawah ini di tag web.config handlers dan Anda akan baik-baik saja.

<add name="Nancy" path="api" verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" allowPathInfo="true" />
Khawaja Asim
sumber
Bisakah Anda menjelaskan apa itu Nancy dan apakah itu perpustakaan yang akan disertakan dalam proyek? Terima kasih!
kebiruan
1

Saya menemukan bahwa kedua cara berfungsi untuk saya: baik pengaturan runAllManagedModulesForAllRequests ke true atau tambahkan ExtentionlessUrlHandler sebagai berikut. Akhirnya saya memilih untuk menambahkan extensionUrLHandler karena runAllManagedModulesForAllRequests memang memiliki dampak kinerja ke situs.

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" 
       type="System.Web.Handlers.TransferRequestHandler" 
       preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
Xuemei
sumber
1

Saya akan menggunakan ini di file Web.config:

<add name="ManagedSpecialNames" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

sebelum standar "ExtensionlessUrlHandler".

Misalnya dalam kasus saya, saya taruh di sini:

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ManagedFiles" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

Jadi Anda memaksa URL dengan pola seperti itu untuk dikelola oleh Anda, alih-alih pengelolaan standar sebagai file dalam pohon direktori aplikasi.

kebiruan
sumber
0

Saya menghadapi masalah yang sama dan keadaan saya di mana saya tidak seharusnya bermain dengan IIS dan pengaturan terkait konfigurasi situs web. Jadi saya harus membuatnya berfungsi dengan membuat perubahan hanya pada level kode.

Poin sederhananya adalah bahwa kasus paling umum di mana Anda akan berakhir memiliki karakter titik di URL adalah ketika Anda mendapatkan beberapa masukan dari pengguna dan meneruskannya sebagai string kueri atau fragmen url untuk meneruskan beberapa argumen ke parameter dalam metode tindakan pengontrol Anda.

public class GetuserdetailsbyuseridController : ApiController
{
     string getuserdetailsbyuserid(string userId)
     {
        //some code to get user details
     }
}

Lihat URL di bawah ini di mana pengguna memasukkan id penggunanya untuk mendapatkan detail pribadinya:

http://mywebsite:8080/getuserdetailsbyuserid/foo.bar

Karena Anda hanya perlu mengambil beberapa data dari server, kami menggunakan GETverb http . Saat menggunakan GETpanggilan, parameter input apa pun hanya dapat diteruskan di fragmen URL.

Jadi untuk mengatasi masalah saya, saya mengubah verba http tindakan saya menjadi POST. POSTKata kerja http memiliki fasilitas untuk meneruskan input pengguna atau non-pengguna dalam tubuh juga. Jadi saya membuat data JSON dan meneruskannya ke badan POSTpermintaan http :

{
  "userid" : "foo.bar"
}

Ubah definisi metode Anda seperti di bawah ini:

public class GetuserdetailsbyuseridController : ApiController
{
     [Post]
     string getuserdetailsbyuserid([FromBody] string userId)
     {
        //some code to get user details
     }
}

Catatan : Lebih lanjut tentang kapan menggunakan GETkata kerja dan kapan menggunakan POSTkata kerja di sini .

NSP
sumber
Bukan solusi yang tepat jika Anda membangun REST API.
Mustafa Ozturk