I'm using Web API 2 (with MVC 5) to access some data from a MongoDb store. This is the action/method:
[Route("api/container/children/{parentId}")]
[HttpGet]
public HttpResponseMessage GetChildren(String parentId) {
ObjectId containerId;
if (!ObjectId.TryParse(parentId, out containerId)) {
IEnumerable<Container> containers = this.Connection.GetCollection<Container>().FindAs<Container>(Query.EQ(Container.FieldNames.ParentId, containerId));
return this.Request.CreateResponse<Container[]>(HttpStatusCode.OK, containers.ToArray());
}
return this.Request.CreateResponse(HttpStatusCode.NotFound);
}
Calling the method from jQuery with a $.get keep getting me a 404 when calling with the parameter ObjectId.Empty (which is 000000000000000000000000), so calling this Url gives me a 404:
/api/container/children/000000000000000000000000
but calling this url works fine:
/api/container/children/0000000000000000
is there some sort of limit to the length of the (id) parameter on Web API 2?
This is not a WebAPI problem.
The bug in the code is actually very simple. Remove the not (!) operator in the if condition
[Route("api/container/children/{parentId}")]
[HttpGet]
public HttpResponseMessage GetChildren(String parentId) {
ObjectId containerId;
if (ObjectId.TryParse(parentId, out containerId)) {
...
}
return this.Request.CreateResponse(HttpStatusCode.NotFound);
}
Related
For ASP.NET Core 6.0 Web API :
What is the best practice on returning an async result that contains a compound result :
JSON representation of object/collection ( T or IEnumerable )
HttpStatusCode
May be, that's something what you needed.
[HttpGet]
public ActionResult<SOMETYPE> Get()
{
return StatusCode(200, SOMEOBJECT);
}
Using ASP.NET Core 3.1 and Microsoft.AspNetCore.OData 7.5.6,
When a HTTP "DELETE" request is sent to an action method, I am unable to get the
query parameter, the resulting parameter value remains set to 0.
Here is my HTTP Request:
https://localhost:8083/api/EventTypes(Id%3D66L)
And my Action Method:
[Route("api/EventTypes({Id})")]
[HttpDelete]
// [AcceptVerbs("DELETE")]
public async Task<IActionResult> Delete(Int64 Id)
{
DynamicParameters param = new DynamicParameters();
param.Add("Id", Id);
await Dapper.DapperORM.ExecuteWithoutReturn("event_type_delete", param);
return Ok();
}
When I inspect the value of Id the value is 0. I have tried changing the type to string, and then the value is set to "Id=66L".
I expect this to work but it does not in my case:
Delete([FromODataUri]Int64 Id)
What is the best/correct way to get the integer value?
Changing the Route Parameter to use this format Id={Id} and using FromODataUri I managed to get the desired parameter value.
e.g.
[Route("api/EventTypes(Id={Id})")]
[AcceptVerbs("DELETE")]
public async Task<IActionResult> Delete([FromODataUri]Int64 Id)
This hits the corresponding method:
https://localhost:44379/annotation/getbytarget/https%3a%2f%2f
whereas this one causes 404:
https://localhost:44379/annotation/getbytarget/https%3a%2f%2fa
The only difference between the two URLs is that the latter has one extra letter (a) at the end. I am calling these URLs from the browser. But firstly, I had tried HttpClient's GetStringAsync method. No difference.
My goal is to call this URL:
https://localhost:44379/annotation/getbytarget/https://analyzer.app/analysis/60be725a980f947a351e2e97
I am encoding this URL so it becomes:
https://localhost:44379/annotation/getbytarget/https%3a%2f%2fanalyzer.app%2fanalysis%2f60be725a980f947a351e2e97
What could be the reason for this error?
This is an ASP.NET Core 3.1 Web API application and the corresponding Web API method is as follows:
[HttpGet("{id}")]
public ActionResult<List<Annotation>> GetByTarget(string id)
{
var annotations = _annotationService.GetByTarget(id);
if (annotations == null)
{
return NotFound();
}
return annotations;
}
I have solved the issue by changing the Web API method's routing signature (I am not sure if routing signature is the correct term). Notice that I have commented out the [HttpGet("{id}")] attribute:
//[HttpGet("{id}")]
public ActionResult<List<Annotation>> GetByTarget(string id)
{
var annotations = _annotationService.GetByTarget(id);
if (annotations == null)
{
return NotFound();
}
return annotations;
}
Now the method accepts calls this way (notice the id parameter):
https://localhost:44379/annotation/getbytarget?id=https%3a%2f%2fanalyzer.app%2fanalysis%2f
Consider this simple controller action:
[HttpGet("{imageId}")]
[ResponseCache(Duration = 604800)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Produces("image/jpeg")]
public async Task<IActionResult> GetImageAsync(int imageId)
{
if (imageId <= 0)
{
return NotFound();
}
byte[] imageBytes = await _imageProvider.GetImageAsync(
imageId,
Request.HttpContext.RequestAborted).ConfigureAwait(false);
if (imageBytes is null)
{
return NotFound();
}
return File(imageBytes, MediaTypeNames.Image.Jpeg);
}
This method works fine, however in telemetry I am getting this for every call:
Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor: Warning: No output formatter was found for content types 'image/jpeg, image/jpeg' to write the response.
Simply commenting out the ProducesAttribute prevents the telemetry from being logged.
I want to keep ProducesAttribute because it enables my Swagger UI page to work. In Swagger it shows this API has an expected output media type of image/jpeg. If I remove the attribute it changes to text/plain and it doesn't render correctly.
So the question is, how can I fix this controller action to not create a bunch of unnecessary telemetry, while also allowing Swagger UI to work correctly?
This first method is fine. But when I add the second method the body of the SWAGGER UI is a bunch of html gibberish. And I creating the route the wrong way?
// GET api/checklist/1288
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
var model = _checkListService.Get(id);
return Ok(model);
}
// http://localhost:64783/api/checklist/GetDelinquentItems?id=1288
[Route("GetDelinquentItems")]
public async Task<IActionResult> GetDelinquentItems(int id)
{
var model = _checkListService.GetDelinquentItems(id);
return Ok(model);
}
That 'html gibberish' (indeed not the most elegant way to show an error) still contains some useful information. The first line says:
500 internal server error
and in the last three lines you can read:
Ambiguos HTTP method for action...CheckListController.GetDelinquentItems... Actions require explicit HttpMethod binding for Swagger
therefore another
[HttpGet("{id}")]
before the GetDelinquentItems() method should solve the problem.