What is the default HTTP verb in WebApi ? GET or P

2019-07-18 23:01发布

问题:

Just curios. I was looking at one of the web projects at internet.

And the code flow is like this:

[RoutePrefix("/person")]
public class PersonController : ApiController
{

    //....
    [Route("/register")]
    public IHttpACtionResult RegisterPerson(PersonDto personDto)
    {
        //....
    }
    //....
}

Did you notice the above code? There is no [HttpGet()] or [HttpPost()] specified. Yet the above code fails for a GET call but works for a POST call.

Any ideas how this method's HTTP-Verb is resolved ?

Note: I know that if a methodname starts with GET or POST, then correspondingly the method is invoked via HTTPGet or HTTPPost. But the method name here starts with Register....

Any ideas how this works?

回答1:

Because you have an argument (PersonDto) for your method (RegisterPerson)...it has to "post" something, or you won't have access to a hydrated dto object.

While this is about WCF, one paragraph sheds a little light..especially on the nature of GET

https://msdn.microsoft.com/en-us/library/bb628610(v=vs.110).aspx

ASP.NET AJAX supports operations that use the HTTP POST and HTTP GET verbs, with HTTP POST being the default. When creating an operation that has no side effects and returns data that rarely or never changes, use HTTP GET instead. Results of GET operations can be cached, which means that multiple calls to the same operation may result in only one request to your service. The caching is not done by WCF but can take place at any level (in a user's browser, on a proxy server, and other levels.) Caching is advantageous if you want to increase service performance, but may not be acceptable if data changes frequently or if the operation performs some action.



回答2:

Default is [HTTPPost] if the method name doesn't match any HTTPVerb.

The action selection happens through GetSupportedHttpMethods() of ReflectedHttpActionDescriptor class.

Please refer to the code in the link below: https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs

 if (supportedHttpMethods.Count == 0)
            {
                // Use POST as the default HttpMethod
                supportedHttpMethods.Add(HttpMethod.Post);
            }


回答3:

In your example Web API will use a media-type formatter to read the value of PersonDto from the request body meaning POST if it is from the URL it is GET you could explicitly force WebApi to use one or the other by using [FromBody] or [FromUri] like:

public HttpResponseMessage GetSample([FromUri] SomeObject foo) { ... }

or

 public HttpResponseMessage PostSample([FromBody] SomeObject foo) { ... }

By default Web API looks at the routing URL first([Route]) data and tries to match it to a route if it can't get the values from the request URI and this may happen when the parameter is a complex type Web API uses a media-type formatter to read the value from the request body.



回答4:

It Depends on you Action Name if it matches any on the Http Verb. For example

In my API i used an Action to get vendors list, now see how it works:

    [Route("Get")]
    public IHttpActionResult GetVendor()
    {
        var vendor = _ivs.GetVendorDetails();

        return Ok(vendor);
    }

Now when i am hitting api using HttpPost I am getting following message:

{ "Message": "The requested resource does not support http method 'POST'." }

however if I am hitting API using HttpGet I am getting the data

 {
   "VendorId": "cc0e7ea1-4751-467b-b60b-be9b5202a511",

    "VendorCode": "Vend1",
    "VendorName": "testvendor",
    "AddressLine1": "AddressLine1",
    "AddressLine2": "AddressLine2",
    "AddressLine3": "AddressLine3",
    "City": "City                          ",
    "PINCode": "12345   ",
    "province": "province                      ",
    "Phone1": "Phone1",
    "Phone2": "Phone2",
    "Phone3": "Phone3",
    "PrimaryPhone": "Phone3    ",
    "CreatedDate": "2017-06-21T15:49:30.207",
    "CreatedBy": "e465e3e2-4156-434e-a444-f9a9626e1cf6",
    "UpdatedDate": "1900-01-01T00:00:00",
    "UpdatedBy": null,
    "IsActive": true
}

Now i am changing the method name

    [Route("Get")]
    public IHttpActionResult Vendor()
    {
        var vendor = _ivs.GetVendorDetails();

        return Ok(vendor);
    }

and hitting API using HttpGet

Now response i am having is:

{ "Message": "The requested resource does not support http method 'GET'." }