How to make controller accept messages from body as well as url in MVC 6 ASP.NET 5

I am currently trying to write a controller in MVC 6 that is capable of accepting data from a post request. The problem is that depending on the client (which is not always a web browser), the data may come in as key value pairs in the request url or as JSON in the request body.

This method currently works for receiving data from a url:

[HttpPost]
public async Task<CaptureResponse> CaptureData(CaptureInfo capture) {
    ...
}

      

After a lot of trial and error (and answers), I figured out that the attribute [FromBody]

points the model nexus in the request body, which is what is required now, since MVC 6 combines WebApi and standard MVC together.The following code parses the data from JSON into the body of the form:

[HttpPost]
public async Task<CaptureResponse> CaptureData([FromBody] CaptureInfo capture) {
   ...
}

      

For simplicity, I would like to somehow combine the two, so that the binder model gives me the data in the same parameter variable. So far, the only way to get the data in one action is to specify two parameters, one for the url and one for the body, and also do some null validation for each, for example:

[HttpPost]
public async Task<CaptureResponse> CaptureData(CaptureInfo capture, [FromBody] CaptureInfo bodyCapture) {
    if (bodyCapture != null) {
        if (bodyCapture.RequiredProperty1!= null
        && bodyCapture.RequiredProperty2!= null) {
            capture = bodyCapture;
        }
    }
    ...
}

      

I tried to specify multiple properties before the input attribute like this:

[HttpPost]
public async Task<CaptureResponse> CaptureData(CaptureInfo [FromQuery][FromRoute][FromForm][FromBody] capture) {
    ...
}

      

But that won't work. Any ideas if something like this is possible?

+3


source to share


2 answers


As far as I know, this is simply not possible. You can of course try workarounds, basically doing all the queries yourself. Sounds good, doesn't it?

If you really want something of your own, I believe the best approach is to have two different endpoints in the controller and a private method for the actual processing. Or perhaps even extract this method into an additional layer of abstraction with the BlaBlaService class (CaptureService in your case, perhaps), responsible for all the dirty work. Sometimes it makes sense to separate your controller layer from your business logic - for testing purposes, for example.



PS: Your idea is very similar to what the approach was in the good old days of .NET and PHP, and trust me, this particular idea is not the one that made those good times. You know MVC is very similar to the REST approach, so each endpoint in your controller should be dedicated to its own function and obey a single and uniform "intuitive" protocol.

The "intuitive" way for developers familiar with REST to send data to a POST request is through the body of the request. I suggest that you consider using this approach as the only one.

0


source


You need to use Request.Form

like:



   string username = HttpContext.Current.Request.Form.GetValues("key1")[0].ToString();
    string password = HttpContext.Current.Request.Form.GetValues("key2")[0].ToString();
    string something = HttpContext.Current.Request.Form.GetValues("key3")[0].ToString();

      

-3


source







All Articles