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.
Related
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 am trying to access the Request property in my ApiController-derived class.
For some reason, Request is null in ExecuteAsync method. I've seen the other questions, so before you ask:
I am not initializing the controller by calling the constructor, it's a regular HTTP POST API call from an external device.
I've tried the same request locally with Fiddler, the behavior is identical.
I am not unit testing.
Before hitting the ExecuteAsync method, my request passes through a delegating handler, and in the delegating handler, my request object exists (I even add some properties without any problem).
At the last line of delegating handler, I call return await base.SendAsync(request, cancellationToken); without a problem and request exists.
Right after than in API controller, HttpContext.Current.Request is not null and accessible without problem.
In API controller, RequestContext is not null and accessible without problem.
In that same line, Request is null.
Why would this occur? I'm on Web API 2.2 (and MVC 5, if relevant).
This is probably due to the fact that you're trying to access HttpContext while working with async/await.
So, you have two options:
Access the request via the ExecuteAsync method 'HttpControllerContext' parameter - controllerContext.Request.
Make sure your web.config is targeting .NET 4.5 and update appSettings with aspnet:UseTaskFriendlySynchronizationContext set to true.
You can read more here - Using HttpContext Safely After Async in ASP.NET MVC Applications.
To better understand what's going on under the hood, I'd recommend:
Understand what is SynchronizationContext - ExecutionContext vs SynchronizationContext
Understand how it is related to ASP.NET - Understanding the SynchronizationContext in ASP.NET.
In a very very high level: in a synchronous server implementations, where the entire request is processed by the same thread, the execution context is stored using TLS (thread local storage), means HttpContext is available anywhere in your code.
In an asynchronous server implementation (async/await), the request may be processed by several threads, and there's a need to pass the execution context between those threads.
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.
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
Is it possible to log every HTTP request made to an ASP.NET Web API, even if the request is malformed, or for some other reason fails to route to one of the controllers.
For example, if a POST method has an Order model as it's parameter, an incorrect request will prevent it from ever reaching the controller's POST method. I'd like to alert someone so that actions can be taken to prevent future failures.
Is there a way to capture these requests further upstream from the controller?
Either use Tracing, you need to implement ITraceWriter as shown below
http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api
Or implement message handlers
http://www.strathweb.com/2012/05/implementing-message-handlers-to-track-your-asp-net-web-api-usage/
http://www.asp.net/web-api/overview/working-with-http/http-message-handlers
Message handlers allow you to change message before it comes to HttpControllerDispatcher, and therefore you can handle common problems with routing and action method selection.
But as the last do not hesitate to use AppFabric logging, when you are hosting on IIS, because it can give you information when something is going wrong before requests come to your Web Application. It handles scenarions with global errors in web application, for example errors with web.config.
If you enable tracing in the ASP.NET Web API per Tracing in ASP.NET Web API, the built-in tracing infrastructure will log the information you are after.
In the case of a malformed request that fails content negotiation, you will see an HttpError occur in the DefaultContentNegotiator.
Here is an example of the simple trace for this type of error:
DefaultContentNegotiator;Negotiate;Type='HttpError',
formatters=[JsonMediaTypeFormatterTracer, XmlMediaTypeFormatterTracer,
FormUrlEncodedMediaTypeFormatterTracer,
FormUrlEncodedMediaTypeFormatterTracer]
The trace writer is given a TraceRecord as its input, which will contain the request information as well as optionally any custom information you might want to use.
The Web API will use the trace writer you configure to trace information throughout the lifecycle of requests. You can use trace writer to trace both the lifecycle events as well as your own controller code.