Ký tự dấu chấm '.' trong MVC Web API 2 cho yêu cầu như api / people / STAFF.45287


106

URL mà tôi đang cố gắng cho phép hoạt động là một URL có kiểu: http://somedomain.com/api/people/staff.33311 (giống như các trang web như LAST.FM cho phép tất cả các loại dấu hiệu trong url RESTFul & WebPage của chúng , ví dụ: " http://www.last.fm/artist/psy'aviah " là url hợp lệ cho LAST.FM).

Các tình huống sau đây hoạt động như thế nào: - http://somedomain.com/api/people/ - trả về tất cả mọi người - http://somedomain.com/api/people/staff33311 - cũng sẽ hoạt động, nhưng không phải như tôi ' m sau khi tôi muốn url chấp nhận một "dấu chấm", như ví dụ bên dưới - http://somedomain.com/api/people/staff.33311 - nhưng điều này mang lại cho tôi

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

Tôi đã thiết lập những thứ sau:

  1. Bộ điều khiển "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 }
        );
    }

Tôi đã thử làm theo tất cả các mẹo của bài đăng blog này http://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx nhưng nó vẫn không hoạt động .. Tôi cũng nghĩ nó khá tẻ nhạt và tôi tự hỏi liệu có cái khác không, cách tốt hơn và an toàn hơn.

Chúng tôi có Id nội bộ của chúng tôi như thế này, vì vậy chúng tôi sẽ phải tìm giải pháp để phù hợp với dấu chấm theo cách này hay cách khác, tốt nhất là theo kiểu "." nhưng tôi sẵn sàng nhận các đề xuất thay thế cho url nếu cần ...


10
Không phải là câu trả lời, nhưng về lý do tại sao bạn nhận được 404 cho somedomain.com/api/people/staff.33311 - theo mặc định, IIS nhìn vào URL này và thấy. dưới dạng phần mở rộng tệp và gọi trình xử lý tệp tĩnh, bỏ qua API MVC của bạn. Câu trả lời bạn được chấp nhận (chạy tất cả các module quản lý cho tất cả các yêu cầu) hoạt động vì bạn buộc mọi yêu cầu để IIS phải đi qua các đường ống dẫn ASP.NET (do đó, bộ điều khiển của bạn)
Henry C

Liên quan chặt chẽ bài đăng ở đây .
RBT

Câu trả lời:


104

Cài đặt sau trong web.configtệp của bạn sẽ khắc phục sự cố của bạn:

<configuration>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />

4
Nó đã thành công. Tuy nhiên, có bất kỳ lỗ hổng nào khi đặt tùy chọn này không? Tại sao đây không phải là hành vi tiêu chuẩn?
Yves Schelpe

2
Ok, đã quan tâm đến bất kỳ ai: Tôi thấy câu hỏi của tôi ở trên được trả lời ở đây trên các câu trả lời được chấp nhận tại thời điểm viết bài (trả lời bằng Kapil Khandelwal): stackoverflow.com/questions/11048863/...
Yves Schelpe

2
Có, nó hoạt động, xe buýt những người khác, tôi muốn biết mô-đun cụ thể nào được yêu cầu để chức năng này hoạt động?
Greg Z.

3
Khi tôi thử điều này, nó sẽ chỉ hoạt động nếu tôi đặt dấu '/' ở cuối đường dẫn. Bất kỳ đề xuất tại sao điều này là? Lưu ý nhỏ, câu trả lời bên dưới bổ sung cụ thể 'UrlRoutingModule' thay vì chạy tất cả các mô-đun, cũng phù hợp với tôi, mặc dù vẫn có vấn đề rằng nó yêu cầu dấu '/' ở cuối để hoạt động.
Nikolaj Dam Larsen

10
stackoverflow.com/a/12151501/167018 rất đáng xem nếu bạn lo lắng (và đúng là như vậy) về tác động hiệu suất của việc bật runAllManagedModulesForAllRequests.
Henry C

140

Nối URL bằng dấu gạch chéo, ví dụ: http://somedomain.com/api/people/staff.33311/thay vì http://somedomain.com/api/people/staff.33311.


3
@AgustinMeriles Câu trả lời của tôi có thể được coi là một cách giải quyết hơn là một câu trả lời thực tế, tùy thuộc vào cách giải thích của bạn về câu hỏi.
Danny Varod

5
Điều đó không hoạt động mặc dù khi dấu chấm ở cuối phần URL như trong / people / member.
eYe

2
Không, nếu cuối cùng tôi không muốn bị chém ?! Nó không nên được yêu cầu.
Josh M.

1
@JoshM. Đây là một cách giải quyết, tôi đã không viết ASP.NET. Ngoài ra, dấu gạch chéo không ảnh hưởng đến yêu cầu. Nó hiện, tuy nhiên, giúp làm cho ý định của bạn rõ ràng hơn như trong google.com/my query goes here/vs google.com/subDomain my query goes here.
Danny Varod

1
Có, đây là cách tốt nhất bạn không cần phải sửa đổi web.config.
Timothy Gonzalez

35

Tôi nhận thấy rằng việc thêm phần sau vào trước khi tiêu chuẩn ExtensionlessUrlHandlergiải quyết được vấn đề cho tôi:

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

Tôi không nghĩ rằng cái tên thực sự quan trọng đến vậy ngoại trừ nó có thể hữu ích nếu IDE của bạn (trong trường hợp của tôi là Visual Studio) đang quản lý cấu hình trang web của bạn.

H / T tới https://stackoverflow.com/a/15802305/264628


Tôi đã thêm nó 'sau' dòng tiêu chuẩn và nó cũng hoạt động tốt.
Jalal El-Shaer

Đây phải là câu trả lời được chấp nhận. Không yêu cầu / ở cuối của uri
daudihus

2
Cảm ơn vì TRƯỚC, vì nó đã không hoạt động sau đó!
Mese

Tôi tin rằng các mô-đun chạy theo thứ tự khai báo, vì vậy hãy luôn đặt những cái cụ thể hơn (hoặc quan trọng hơn) trước những cái chung chung hơn.
BrianS

24

Tôi không biết mình thực sự đang làm gì, nhưng sau khi chơi với câu trả lời trước đó một chút, tôi đã nghĩ ra một giải pháp khác, có lẽ phù hợp hơn,:

<system.webServer>
<modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</modules>
</system.webServer>

Cảm ơn, tôi cũng không biết nó đang làm gì nhưng nó có vẻ tốt hơn so với giải pháp khác.
Thomas

1
dường như di chuyển mô-đun định tuyến url (là những gì bắt được yêu cầu bao gồm một phần mở rộng và sau đó cố gắng xử lý nó dưới dạng tệp) vào cuối danh sách các mô-đun, đủ để đặt nó sau khi mô-đun xử lý yêu cầu api . IMHO, đây là cách giải quyết tốt nhất có sẵn từ những cái tôi đã nhìn thấy trên SO, ít nhất ATTOW
James Manning

1
Đây không phải là việc di dời đến cuối danh sách, mà là loại bỏ điều kiện tiên quyết mặc định là mô-đun này chỉ chạy cho các trình xử lý được quản lý. Cấu hình mặc định sử dụng định dạng này:<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler" />
theta-fish

Cảm ơn - điều đó sẽ giải thích hành vi.
Greg Z.

8

Tôi thấy rằng tôi cần phải làm nhiều việc hơn là chỉ đặt runAllManagedModulesForAllRequeststhuộc tính thành true. Tôi cũng phải đảm bảo rằng trình xử lý URL không có tiện ích mở rộng đã được định cấu hình để xem tất cả các đường dẫn. Ngoài ra, có một cài đặt cấu hình thưởng khác mà bạn có thể thêm vào sẽ hữu ích trong một số trường hợp. Đây là Web.config đang hoạt động của tôi:

<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>

Đặc biệt, lưu ý rằng thuộc tính ExtensionlessUrlHandler-Integrated-4.0của nó pathđược đặt thành *đối nghịch với *.(ví dụ).


Tôi chỉ nhận được một chút của path="*.". Chỉ tò mò, lý do người ta đặt điều đó là path="*."gì?
JustinP8

Trên thực tế, tôi đã thay đổi nó thành path="*"và gặp sự cố vì chúng tôi đang lưu trữ một trang web tài liệu song song với WebAPI của chúng tôi và trang web đó có vấn đề với .jpg, .png và các tệp khác có phần mở rộng.
JustinP8

@ JustinP8 Bạn cũng đã đặt <modules runAllManagedModulesForAllRequests="true" />? Điều đó sẽ làm cho .NET xử lý các tệp tĩnh đó.
Josh M.

1
Đúng. Tôi say mê làm điều đó. Tôi không thực sự thích điều đó vì bây giờ tất cả các tệp tĩnh đều đi qua đường ống .NET. May mắn thay, vì đây là một dịch vụ webAPI nên chỉ có nội dung Swagger và Swashbuckle cho tài liệu API / trang trợ giúp bị ảnh hưởng.
JustinP8

tôi thấy điều này đã phá vỡ tất cả các yêu cầu tệp tĩnh. lỗi 500. Tôi đã đặt runAllManaged ... thành true.
Sam

2

Tôi gặp khó khăn trong tình huống này nhưng việc nối thêm / ở cuối URL trông không rõ ràng đối với tôi.

vì vậy chỉ cần thêm bên dưới trong thẻ web.config handlers và bạn sẽ có thể sử dụng.

<add name="Nancy" path="api" verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" allowPathInfo="true" />

Bạn có thể giải thích Nancy là gì và liệu nó có phải là một thư viện được đưa vào dự án không? Cảm ơn!
hơi xanh

1

Tôi thấy rằng cả hai cách đều phù hợp với tôi: đặt runAllManagedModulesForAllRequests thành true hoặc thêm ExtentionlessUrlHandler như sau. Cuối cùng, tôi chọn thêm extensionUrLHandler vì runAllManagedModulesForAllRequests có tác động đến hiệu suất cho trang web.

<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>

1

Tôi sẽ sử dụng cái này trong tệp Web.config:

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

trước "ExtensionlessUrlHandler" tiêu chuẩn.

Ví dụ trong trường hợp của tôi, tôi đặt nó ở đây:

<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>

Vì vậy, bạn buộc bạn phải quản lý các URL có dạng như vậy, thay vì quản lý tiêu chuẩn dưới dạng tệp trong cây thư mục ứng dụng.


0

Tôi phải đối mặt với cùng một vấn đề và những trường hợp mà tôi không được phép chơi với IIS và các cài đặt liên quan đến cấu hình trang web. Vì vậy, tôi phải làm cho nó hoạt động bằng cách chỉ thực hiện các thay đổi ở cấp mã.

Điểm đơn giản là trường hợp phổ biến nhất mà bạn sẽ có ký tự dấu chấm trong URL là khi bạn nhận một số thông tin đầu vào từ người dùng và chuyển nó dưới dạng chuỗi truy vấn hoặc phân đoạn url để truyền một số đối số cho các tham số trong phương thức hành động của bộ điều khiển của bạn.

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

Hãy xem URL bên dưới nơi người dùng nhập id người dùng của mình để lấy thông tin chi tiết cá nhân của anh ấy:

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

Vì bạn chỉ cần tìm nạp một số dữ liệu từ máy chủ, chúng tôi sử dụng GETđộng từ http . Trong khi sử dụng GETlệnh gọi, bất kỳ tham số đầu vào nào chỉ có thể được chuyển trong các đoạn URL.

Vì vậy, để giải quyết vấn đề của mình, tôi đã thay đổi động từ http của hành động thành POST. POSTĐộng từ Http cũng có khả năng chuyển bất kỳ đầu vào của người dùng hoặc không phải người dùng nào trong nội dung. Vì vậy, tôi đã tạo một dữ liệu JSON và chuyển nó vào phần thân của POSTyêu cầu http :

{
  "userid" : "foo.bar"
}

Thay đổi định nghĩa phương pháp của bạn như sau:

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

Lưu ý : Thông tin thêm về thời điểm sử dụng GETđộng từ và thời điểm sử dụng POSTđộng từ ở đây .


Không phải là giải pháp thích hợp nếu bạn đang xây dựng API REST.
Mustafa Ozturk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.