Usage of QueryString parameters in MVC with HTTP Post - asp.net-mvc-3

I was recently debugging an ASP.NET MVC application (Firefox + Firebug) and I ran into interesting (to me) scenario, all GET requests as expected were passing parameters in querystring, most POST requests were just posting inputs in the form, however there were some POST requests that mixed both querystring parameters and form inputs.
Interestingely enough MVC model binder had no problem at all to build a model from a mix of querystring and posted parameters. Is it a valid and accepted pattern in ASP.NET MVC and HTTP, or is it more of a fault-tolerant implementation of model-binder?

This is by design - the default MVC model binder will try to match the model parameters from both the URI (query string and/or route data) and the body.
Of course, you could implement your own model binder that behaves differently.
By the way, in ASP.NET Web API, this behavior is no longer like that, and the URI and body parameters are not mixed.

Related

What is the difference between method handlers such .get, .post and actions such as .list, .create

I am learning Django Rest Framework and one of the things I have noticed is that Viewsets provide actions such as .list, .post instead of method handlers such as .get, .post which in turn are provided by Views. The documentation says that actions are more flexible than method handlers but I can't seem to find any reason for this. Could you please share some information on why does Viewsets use actions and not the method handlers?​
request handlers like .get() and .post() are based on http request methods, while actions like .create() or .list() are from a functionality point of view. Suppose you have a view class that can return a single user's info by user id or return all users in sorted order. These two requests are all GET requests from the client side, but with different parameters and purposes. If you just want to use .get() handler in this case you will need to define two view functions and register the two urls in url config. Or you can use ViewSet class or generic view with mixins that has action functions .list() and .retrieve() to handle these requests, then using router class to set the url configs that follows the REST url standards.
GET and POST are the only HTTP methods to use when dealing with forms.
Django’s login form is returned using the POST method, in which the browser bundles up the form data, encodes it for transmission, sends it to the server, and then receives back its response.
GET, by contrast, bundles the submitted data into a string, and uses this to compose a URL. The URL contains the address where the data must be sent, as well as the data keys and values. You can see this in action if you do a search in the Django documentation, which will produce a URL of the form https://docs.djangoproject.com/search/?q=forms&release=1.
GET and POST are typically used for different purposes.
Any request that could be used to change the state of the system - for example, a request that makes changes in the database - should use POST. GET should be used only for requests that do not affect the state of the system.
GET would also be unsuitable for a password form, because the password would appear in the URL, and thus, also in browser history and server logs, all in plain text. Neither would it be suitable for large quantities of data, or for binary data, such as an image. A Web application that uses GET requests for admin forms is a security risk: it can be easy for an attacker to mimic a form’s request to gain access to sensitive parts of the system. POST, coupled with other protections like Django’s CSRF protection offers more control over access.
On the other hand, GET is suitable for things like a web search form, because the URLs that represent a GET request can easily be bookmarked, shared, or resubmitted.

Laravel Service layer: passing HTTP request from controller to service

I am developing a Laravel application and using a Service layer pattern to isolate business logic. What I come across in all tutors/articles is passing the HTTP request object from the controller directly into the service. To me, it goes against the principle of a service being an API-independent piece of code that has a single responsibility for a certain functionality. Imagine I would like to call the service from the command line or from an event handler, I would then have to construct an HTTP Request object to pass to the controller.
Same goes for validation: as far as I understand, the validator would on failure either redirect the user back (which may have no sense in the case of command line or event handler) or return an HTTP error.
On the other hand, with a lot of form fields, there should be some structure to pass the data in, and the form itself already gives such structure.
What are best practices regarding this?

Attribute Routing changes WebAPI pipeline

I've got a .NET WebApi solution. I'm constraining access to HTTPS but conditionally allowing HTTP traffic. One of the conditions is that all HTTP requests must use the HTTP POST method, passing the x-http-method-override header to supply the intended method so the request can be properly routed. I've configured a global DelegatingHandler to validate all incoming requests and perform the redirection if needed.
With standard routing everything works great. When I configure AttributeRouting things go off the rails. It appears that AttributeRouting attempts to locate the route before the DelegatingHandler modifies the request, resulting in improper routes or IIS 404 errors. Is there a way to intercept the route before the AttributeRouting handler resolves the route?
More info: The project is hosted on IIS (not self hosted). The AttributeRouting I'm using is what comes in WebApi 2.0. The DelegatingHandler is defined thusly in App_Start:
GlobalConfiguration.Configuration.MessageHandlers
.Add(new MyCustomDelegateHandler());
AttributeRouting is configured simply using:
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
The routes are defined using the attributes:
[HttpGet("api/test/v1/users")]
Couple of question for clarity...Is this a Selfhost or Webhost(IIS) scenario? By AttributeRouting you mean the built-in Web API 2 attribute routing and not TimMcCall's attribute routing nuget package...right?
There have always been differences between when route matching occurs between Selfhost and Webhost. In Selfhost, route matching happens after message handlers are run, where as in case of Webhost route matching happens before message handlers are run.
If your scenario is Webhost, then I would expect the behavior to not change...but if your are seeing different behavior, then can you share how your route configuration (WebApiConfig.cs & the attributed controller/action) look like?
In Webhost, to intercept requests before route matching happens, you could create a Owin middleware which sits before the request is received by Web API. In this middleware you can modify the request details as you need.
NOTE:
Based on the update "More Info" in the post above, pre-RTM bits were being used where this seems to be an issue and this is not longer a problem with the final RTM bits.

Is server-side validation an appropriate use of ASP.NET WebAPI ApiController action

Before WebAPI, I did all client-side remote validation calls using regular MVC action methods. With WebAPI, I can now have POST, PUT, DELETE, and GET methods on an ApiController. However, validation still needs to happen.
I have successfully been able to put remote validation action methods on an ApiController and get them to work. Before submitting a POST, PUT, or DELETE for a resource, the client can POST to one or more validation URL's to validate user input and receive appropriate validation messages.
My question is, should these remote validation actions be on an ApiController? Or a regular MVC controller? It seems to me having them all in the ApiController makes the most sense, because that class can then encapsulate everything having to do with resource (and resource collection) mutations.
Update: reply #tugberk
I should elaborate. First, we are not using DataAnnotations validation. There are already rich validation rules and messages configured on the domain layer commands using FluentValidation.NET. Many of the validation classes use dependency injection to call into the database (to validate uniqueness for example). FluentValidation has good pluggability with MVC ModelState, but I have not found a good way to plug it into WebAPI ModelState yet.
Second, we are doing validation at the POST, PUT, and DELETE endpoints. Clients do not need to know the validation endpoints in order to discover what went wrong. Here is an example:
var command = Mapper.Map<CreateCarCommand>(carApiModel);
try
{
_createHandler.Handle(command);
}
catch (ValidationException ex)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
}
Clients will get a 400 response along with a message indicating what went wrong. Granted, this is not as granular as the response in the example you linked to. Because we are just returning a string, there is no easy way to parse out which fields each validation message belongs to, which is needed for our own HTML + javascript client of the API. This is why I spiked out adding more granular validation endpoints (as a side note, they are consumed by field-specific knockout-validation calls on our javascript client).
I am assuming that you are referring to something similar to ASP.NET MVC Remote Validation by saying remote validation. In that case, I don't think that your HTTP API needs a remote validation. Think about a scenario where I need to consume your HTTP API with my .NET application and assume that you have a remote validation. Two things bother me here:
That remote validation is not discoverable unless you are providing a .NET client for your API by yourself and put that logic inside that client.
Assuming that the remote validation is there for the .NET client and the application will make a validation call to the server before sending the actual request, this is just a overkill.
In my opinion, the user send a request to your API and you should make the validation there. You can find a sample from the following URL:
ASP.NET Web API and Handling ModelState Validation

Are there any MVC web frameworks that support multiple request types?

In every MVC framework I've tried (Rails, Merb, Waves, Spring, and Struts), the idea of a Request (and Response) is tied to the HTTP notion of a Request. That is, even if there is an AbstractRequest that is a superclass of Request, the AbstractRequest has things like headers, request method (GET, POST, etc.), and all of the other things tied to HTTP.
I'd like to support a request-response cycle over SMS, Twitter, email, or any other medium for which I can make an adapter. Is there a framework that does this particularly well?
The only other option I've thought of is creating, for example, a Twitter poller that runs in a separate thread and translates messages into local HTTP requests, then sends the responses back out.
If there were a good framework for multiple request media, what would routing look like? In Rails, the HTTP routing looks something like:
map.connect 'some/path/with/:parameter_1/:paramter_2', :controller => 'foo', :action => 'bar'
How would a Twitter or SMS route look? Regular expressions to match keywords and parameters?
I haven't seen one. The issue is that the request is also tied to the host, and the response is tied to the request.
So if you get a request in via email, and a controller says to render view "aboutus", you'd need the MVC framework to know how to :
get the request in the first place - the MVC framework would almost need to be a host (IIS doesn't get notified on new emails, so how does your email polling code get fired?)
allow flexible route matching - matching by path/url wouldn't work for all, so request-specific controller routing would be needed
use the aboutus email view rather than the SMS or HTTP view named "aboutus"
send the response out via email, to the correct recipient
A web MVC framework isn't going to cut it - you'll need a MVC "host" that can handle activation through web, sms, email, whatever.
The Java Servlet specification was designed for Servlets to be protocol neutral, and to be extended in a protocol-specific way - HttpServlet being a protocol-specific Servlet extension. I always imagined that Sun, or other third poarty framework providers, would come up with other protocol-specific extensions like FtpServlet or MailServlet, or in this case SmsServlet and TwitterServlet.
Instead what has happened is that people either completely bypassed the Servlet framework, or have built their protocols on top of HTTP.
Of course, if you want to implement a protocol-specific extension for your required protocols, you would have to develop the whole stack - request object, response object, a mechanism of identifying sessions (for example using the MSISDN in an SMS instead of cookies), a templating and rendering framework (equivalent of JSP) - and then build an MVC framework on top of it.
You seem to be working mostly with Java and/or Ruby, so forgive me that this answer is based on Perl :-).
I'm very fond of the Catalyst MVC Framework (http://www.catalystframework.org/). It delegates the actual mapping of requests (in the general, generic sense) to code via engines. Granted, all the engine classes are currently based on HTTP, but I have toyed with the idea of trying to write an engine class that wasn't based on HTTP (or was perhaps tied to something like Twitter, but was separated from the HTTP interactions that Twitter uses). At the very least, I'm convinced it can be done, even if I haven't gotten around to trying it yet.
You could implement a REST-based Adapter over your website, which replaces the templates and redirects according to the input parameters.
All requestes coming in on api.yourhost.com will be handled by the REST based adapter.
This adapter would allow to call your website programmatically and have the result in a parseable format.
Practically this means: It replaces the Templates with an own Template Engine, on which this things happen:
instead of the assigned template, a generic xml/json template is called, which just outputs a xml that contains all template vars
then you can make your Twitter Poller, SMS Gateway or even call it from Javascript.

Resources