问题
This is causing me a bit of a headache. Ultimately, I'm trying to return an image but I've been experimenting and simplified this to using a string.
What I want: go to URL:
http://xxx/api/helloworld/1
Responds with: "Hello world!"
The following web api declarations work for the url supplied;
public string Get([FromUri]int id) { return "Hello World"; }
public Task<string> Get([FromUri]int id) { return "Hello World"; }
What does NOT work;
public HttpResponseMessage Get([FromUri]int id)
{
return Request.CreateResponse<string>(HttpStatusCode.OK, "Hello World");
}
public HttpResponseMessage Get([FromUri]int id)
{
HttpResponseMessage response = new HttpResponseMessage();
string text = "Hello World";
MemoryStream test = new MemoryStream();
test.Write(ConversionUtilities.ToBytes(text) /*custom string->byte[] method, UTF-8 encoding*/, 0, text.Length);
response.Content = new StreamContent(test);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
response.StatusCode = HttpStatusCode.OK;
return response;
}
What happens when I have a Get() with a return type of HttpResponseMessage is the following error is returned;
No HTTP resource was found that matches the request URI "http://xxx/api/helloworld/1"
This error only appears for this particular return type. Now, my routing in the WebApiConfig.cs file is as follows (and works for "string" return types);
// Controller with ID
// To handle routes like "/api/VTRouting/1"
config.Routes.MapHttpRoute(
name: "ControllerAndId",
routeTemplate: "api/{controller}/{id}",
defaults: null,
constraints: new { id = @"^\d+$" } // Only integers
);
// Controllers with Actions
// To handle routes like "/api/VTRouting/route"
config.Routes.MapHttpRoute(
name: "ControllerAndAction",
routeTemplate: "api/{controller}/{action}"
);
// Controller Only
// To handle routes like "/api/VTRouting"
config.Routes.MapHttpRoute(
name: "ControllerOnly",
routeTemplate: "api/{controller}"
);
Any thoughts? I'm stumped as to the return type behaviour :-S
回答1:
Found the cause! I had created a blank api controller as per the template which worked. Cue a bit of copy/pasting to narrow down the cause. It's subtle and the code that I posted worked because I changed the variable names for posting publicly - which was ultimately the cause of the issue. Go figure.
To replicate, create your template as per normal. This will create a method;
public string Get(int id)
Change this to;
public string Get(int personID)
And try to run. You'll get the error described as above. It seems that the declaration of the Get/Post/etc parameters MUST match that specified in the routing. If you change the parameter to "personID" as I did, you can fix by either renaming your parameter back to the default "id" or modifying your routing with the updating name;
config.Routes.MapHttpRoute(
name: "ControllerAndId",
routeTemplate: "api/{controller}/{personID}",
defaults: null,
constraints: new { personID = @"^\d+$" } // Only integers
);
Note the "{personID}" in the routeTemplate and constraint parameters. The name of this field MUST match that of the name of your parameter. It never actually says this in the doc when looking up how to download files or just generally looking at web api. It probably does when going into a high level of detail on routing/mvc but I have to say that this easily trips up a n00b not familiar with either. Mind you, my more experienced collegues didn't spot this either :-). I hope this helps others with the same pain!
来源:https://stackoverflow.com/questions/14857370/web-api-get-route-not-working-when-return-type-is-httpresponsemessage