I have a following method in my controller:
[AcceptVerbs("GET", "OPTIONS", "HEAD")]
[OutputCache(Duration="3600" VaryByParam="None" VaryByHeader="Access-Control-Request-Headers;Origin")]
public new ActionResult Index()
{
//action body
}
It is handling both GET and OPTIONS (CORS) calls and so far there has been no problem. I've recently added the OutputCache attribute and started wondering if it's possible to cache a flawed OPTIONS response, by calling the GET. Namely, let's say a user with malicious intents calls my GET call with the CORS headers that I vary on. Is it possible that a user making the OPTIONS call with the same headers (this time used properly), will instead get the response from the previously cached GET, therefore nuking the whole OPTIONS call for the duration of the cache?
I was looking for an information, if the HTTP method is considered when creating an output cache entry, but just can't find it anywhere. I have tested this locally and it seemed that the GET and OPTIONS output could never get mixed up, no matter how hard I messed with the headers. Still, I would be much more relieved if I knew that what I described could really never happen.
Related
Over the past couple weeks I've been working with an ASP.NET Core Backend(Remote Ubuntu Machine, SSH only, Kestrel).
When sending an HTTP-Request to the Server oftentimes it won't be handled the way I expected it to.
Examples:
For POSTs: An action parameter will be null or 0 or an empty string
the action method isn't executed at all
Is there a way to see the headers, body, etc. of the request that arrived at the Server?
How is the body data processed before the corresponding action method is called?
I've been reading the Console Output and setting breakpoints to figure out whats going on.
Which is fine if there's an Exception thrown or theres something going wrong inside the action method.
But it doesn't help me understand what's happening before the action method is executed.
You can add a middleware in the pipeline to inspect any requests. In the middleware, you will have access to the HttpContext and all its properties (i.e. the request and its headers). As long as you place your app.Use() call before your app.UseMvc() call, you will have access to the request before it enters an action.
More info on middleare is here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware
Once it enters an action, you have access to the Request object in the controller as well. So you can inspect anything on the request (i.e. headers) however you prefer (locals window, watch window, etc.).
All the properties you can access if you inherit from ControllerBase are here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase
As Polyfun mentioned, the best approach would be to add robust logging.
I need to be able to call my SS services from the controllers of an MVC application. Ideally i'd like to call them in-process to avoid the overhead of buiding a http request etc.
From scouring documentation I feel there are 2 suggested methods, but neither work fully.
1) ServiceGateway - Use the service gateway. This calls validation filters, but does not call other customer filters I've added. No option to applyFilters.
2) HostContext.ServiceController.Execute - There is a dedicated option on this method called applyFilters, and when I set it to true it works and applies filters and validation (though it only executes GlobalFilters, not TypedRequestFilters). However, if [CacheResponse] attribute is set on the service it overwrites and flushes a response to my client overriding the flow of the MVC controller and i don't know how to stop this. It does not do this if I set to applyFilters to false or if I take CacheResponse off. Changing the priority of the cache has no effect.
I'm calling the Execute method as follows from within an Action method on my controller:
HostContext.ServiceController.Execute(serviceRequest, HostContext.GetCurrentRequest(), true);
Before this method even returns control a response is flushed to the webpage on Chrome and then nothing/null is returned from method.
I feel there is regarding point 1) a feature missing and point 2) a bug in the implementation, though am not confident enough in my knowledge of SS to remedy either! Please help!
Thanks.
Filters are executed as part of the HTTP Request Pipeline and can terminate the current Request with a custom HTTP Response. You can check IRequest.IsClosed after executing the Request to check if it has been terminated by a Request Filter. They're behavior is incompatible with internal Gateway requests so there's no option to execute them in the Gateway.
I've marked these ServiceController methods as an In Process Request in this commit which should resolve the issue with the [CacheResponse] attribute which ignores In Process Requests.
This change is available from v4.5.13 that's now available on MyGet.
I always wonder what is the best error response code in folowing situation:
public IActionResult Index(Guid id)
{
var entity = _dbContext.Entities.Find(id);
if (entity == null)
{
return NotFound(); //??
}
return View(entity)
}
404 - Not Found seems most appropriate, however, from debugging point of view, non-existing ID and wrong controller/action names are very different errors.
Anyway, I've decided to return custom error page with more explanatory message, so I can differentiate between 404 and 404.
How to return custom 404 page from Controller's Action and default 404 in other cases?
I would like to avoid returning HttpResponseMessage, since I would need to change return type of the Action.
PS: In comments you may vote for 404 resp other response code you would use in this particular case.
Take a look at this question first.
Theoreticaly you shouldn't use HttpStatus-codes as Application Error Codes.
However, on a public website, 404 has one specific meaning:
The requested resource could not be found but may be available in the
future. Subsequent requests by the client are permissible.
Calling /getresource/347d2f3a-bd0f-4d0b-8c05-2e7f3f8f265e is a resource. If this is not available you should use 404. If it is available, then 200. That's perfectly fine.
Google even says, you should send 404. From the google support:
Returning a code other than 404 or 410 for a non-existent page (or
redirecting users to another page, such as the homepage, instead of
returning a 404) can be problematic. Firstly, it tells search engines
that there’s a real page at that URL. As a result, that URL may be
crawled and its content indexed. Because of the time Googlebot spends
on non-existent pages, your unique URLs may not be discovered as
quickly or visited as frequently and your site’s crawl coverage may be
impacted (also, you probably don’t want your site to rank well for the
search query
For the implementation, I would just throw a custom NotFoundException (If you want to setup more meaningfull information) with all the data you need, and handle it globaly through the ExceptionFilterAttribute. There you can turn it into a 404 response.
Of course you can let the original exception just bubble up to the ExceptionFilterAttribute, but then you have not that many possibilites for making it meaningfull.
You can utilize the CreateResponse extension method and would do something as follows:
return Request.CreateResponse(HttpStatusCode.NotFound, "foobar");
I've used the HttpStatusCode.NoContent for something like this before. It really depends on what your business logic is and how you want to handle these cases. NoContent will result in a successful http call where as NotFound will be an error. NotFound will trigger your default MVC error page route(if you have that setup) and NoContent won't. Is this a response that is possible through normal use/traversing of the app or is it only something that will occur if a malicious user is tampering with urls? All of those pieces are what I take into consideration determining which http status code I want to return. Hope this helps!
I have a POST IHttpActionResult method in my API controller that uses the [FromBody] attribute.
[Route("gameworld/generate")]
public IHttpActionResult PostNewWorld([FromBody] WorldData json)
Normally, when I want to test my controllers locally, I just goto the URL.
However, I can't do that with this method because I get this error:
The requested resource does not support http method 'GET'.
Is there a way for my local environment to see that this is a POST event?
Thanks!
First of all, ASP.NET Web Api is smart enough to deserialize your json into an object, so unless you really expect a string value in the body you can just put your type in there.
[Route("gameworld/generate")]
public IHttpActionResult PostNewWorld([FromBody] WorldData newWorld)
You can either test it manually with tools like Postman or Swagger, but manual tests are usually done once and then forgotten. This opens up for regression bugs where you make a change in the future, forget to retest the endpoint and break the application using the api.
Therefor, you should write unit tests to keep checking your code and prevent regression bugs. I've been using MyTested.WebApi on several projects and you can test both the routing and the actual calls. For example:
MyWebApi
.Server()
.Working()
.WithHttpRequestMessage(req => req
.WithRequestUri("api/bugs")
.WithMethod(HttpMethod.Post)
.WithContent(myJsonString)
.ShouldReturnHttpResponseMessage()
.WithStatusCode(HttpStatusCode.Created)
.WithResponseModelOfType<BugReport>()
.Passing(r => r != null);
There's a lot of things to be tested, so be sure to read the docs.
I want to know what is the best way to avoid the reinsertion of data in ASP.net.
I am currently doing
Response.Redirect('PageURL');
Thanks in Advance
Don't put your insertion code in the Page_Load method, or if you are, make sure you are checking Page.IsPostBack first.
Yes, normally we have an identity autoincrement number id, wich should be sent back to your form after the insertion. So you just have to check on server if that number is > 0 and execute an update instead of an insert.
Your redirect solution is valid. This pattern is called Post/Redirect/Get.
Post/Redirect/Get (PRG) is a web development design pattern that
prevents some duplicate form submissions, creating a more intuitive
interface for user agents (users). PRG implements bookmarks and the
refresh button in a predictable way that does not create duplicate
form submissions.
When a web form is submitted to a server through an HTTP POST request,
a web user that attempts to refresh the server response in certain
user agents can cause the contents of the original HTTP POST request
to be resubmitted, possibly causing undesired results, such as a
duplicate web purchase.
To avoid this problem, many web developers use the PRG pattern[1] —
instead of returning a web page directly, the POST operation returns a
redirection command. The HTTP 1.1 specification introduced the HTTP
303 ("See other") response code to ensure that in this situation, the
web user's browser can safely refresh the server response without
causing the initial HTTP POST request to be resubmitted. However most
common commercial applications in use today (new and old alike) still
continue to issue HTTP 302 ("Found") responses in these situations.
Use of HTTP 301 ("Moved permanently") is usually avoided because
HTTP-1.1-compliant browsers do not convert the method to GET after
receiving HTTP 301, as is more commonly done for HTTP 302.[2] However,
HTTP 301 may be preferred in cases where it is not desirable for POST
parameters to be converted to GET parameters and thus be recorded in
logs.
http://en.wikipedia.org/wiki/Post/Redirect/Get