Cannot bind JSON to ASP.NET Model in multi part post - asp.net-mvc

I am using ASP.NET MVC3 controller to receive multi-part form post from WP7 app. The format of the post is something as follows:
{User Agent stuff}
Content-Type: multipart/form-data; boundary=8cdb3c15d07d36a
--8cdb3c15d07d36a
Content-Disposition: form-data; name="user"
Content-Type: application/json
{"UserName":"ashish","Password":"ashish"}
--8cdb3c15d07d36a--
And my controller looks like:
public class User
{
public string UserName { get; set;}
public string Password { get; set; }
}
[HttpPost]
public JsonResult CreateFeed(User user)
{
}
What I am seeing is that User is not bound to json and user object is always null. I tried making user string and manually bound it to User class using DataContractJsonSerializer and it does create and assign an object but I am baffled as to why it does not work.
I tried using non-multi-form post and found it works with the same json. Any help would be appreciated.
I saw these posts: ASP.NET MVC. How to create Action method that accepts and multipart/form-data and HTTP spec http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 while coming up with my code.

The answer you're looking for is here
You have to read it in as a string and parse that internally.
So your action would look like this:
[HttpPost]
public JsonResult CreateFeed(string jsonResponse)
{
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
User user = jsonSerializer.Deserialize<User>(jsonResponse);
}
Or if you don't have nice helpful Content-Disposition with names to associate with the controller action methods you can do something like the below:
[HttpPost]
public JsonResult CreateFeed()
{
StreamReader reader = new StreamReader(Request.InputStream);
string jsonResponse = reader.ReadToEnd();
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
User user = jsonSerializer.Deserialize<User>(jsonResponse);
}
This approach is further outlined here

Related

ASP.NET WebAPI Null value in post body?

I have just started learning WebAPI today and I can't figure out why "account" is always null.
Request
Content-Type: application/json; charset=utf-8
Request-Body: {"account":{"email":"awd","password":"awad","isNewsletterSubscribed":false}}
WebAPI
public class AccountsController : ApiController
{
public void Post([FromBody] string account)
{
// account is null
}
}
Shouldn't account contain a json string in this case?
Shouldn't account contain a json string in this case?
That would depend on the specific Content-Type request header you set when you send the request. For example if you used application/x-www-form-urlencoded which is the default then your request body payload must have looked like this:
={"account":{"email":"awd","password":"awad","isNewsletterSubscribed":false}}
Notice the = character at the beginning. That's one of the biggest weirdest things I have ever encountered. Since you can bind only one parameter from the body if the request the Web API doesn't expect a parameter name, but just the value.
This being said, your request payload looks more like a JSON. So it would make far more sense to design a view model and use Content-Type: application/json when sending the request. Binding a JSON object to a string is not common practice.
So:
public class UserViewModel
{
public string Email { get; set; }
public string Password { get; set; }
public bool IsNewsletterSubscribed { get; set; }
}
public class AccountViewModel
{
public UserViewModel Account { get; set; }
}
and then your controller action will simply take the view model as parameter. In this case yo udon't need to decorate it with the [FromBody] attribute because by convention in Web API the default model binder will attempt to bind complex types from the body of the request:
public class AccountsController : ApiController
{
public HttpResponseMessage Post(AccountViewModel model)
{
// work with the model here and return some response
return Request.CreateResponse(HttpStatusCode.OK);
}
}
Also notice that since HTTP is a request/response protocol it makes much more sense to have your Web API controller actions return response messages as shown in my example rather than just having some void methods. This makes the code more readable. You immediately understand how the server will respond and with what status code to the specified request.

MVC 3 JSON string not serializing into Controller action

Currently using MVC3 and using jQuery $.post function to send the ajax request to the controller action called "SearchInitiated". I'm having a little bit of a head-scratcher here because I'm not sure exactly where my issues lies. I'm sure its something minor that I have overlooked.
When I call my Controller method from an AJAX call, I am passing a json object (stringified) to a controller action. See below:
Request Headers from Chrome
Accept:/ Content-Type:application/x-www-form-urlencoded;
charset=UTF-8 User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64)
AppleWebKit/537.17 (KHTML, like Gecko)
Chrome/24.0.1312.52 Safari/537.17
X-Requested-With:XMLHttpRequest
Form Dataview
connectorId:1
sessionId:97e2d8b2-be9e-4138-91ed-42ef9c6a2cd6
party:
{"Tag":null,"PartyIdentifier":"1","Address":null,"Address2":null,"BusinessName":"","CellPhoneNumber":null,"CIF":"","City":null,"Country":null,"DateOfBirth":null,"EMailAddress":null,"EmploymentTitle":null,"EmployerAddress":null,"EmployerAddress2":null,"EmployerCity":null,"EmployerName":null,"EmployerPhoneNumber":null,"EmployerState":null,"EmployerZip":null,"Fax":null,"Firstname":"TEST","Lastname":"USER","MailingAddress":null,"MailingAddress2":null,"MailingCity":null,"MailingState":null,"MailingZip":null,"Middlename":null,"PhoneNumber":null,"State":null,"TIN":"1111111","WorkPhoneNumber":null,"Zip":null}
javascript
var parties = #(Html.Raw(Json.Encode(Model.SearchParties)));
function SearchForCustomer(id)
{
var currentSelectedParty = GetPartyById(id)
//SearchPost is a wrapper for $.ajax using default values for dataType and contentType
SearchPost(URL, {
'connectorId': '#Model.ConnectorId',
'sessionId': '#Model.SessionId',
'party' : JSON.stringify( currentSelectedParty )
}
}
Controller
public ActionResult SearchInitiated(int connectorId, string sessionId, SearchParty party)
{
code here....
}
public class SearchParty
{
public SearchParty();
public SearchParty(string lastname, string firstname);
public string Address
{
get;
set;
}
public string City
{
get;
set;
}
public string Country
{
get;
set;
}
public string DateOfBirth
{
get;
set;
}
.... etc etc
}
However, the party object is null.
If I change the code to the following, everything deserializes correctly into the strongly typed object.
public ActionResult SearchInitiated(int connectorId, string sessionId, string party)
{
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
SearchParty sp =
json_serializer.Deserialize<SearchParty>(party);
}
I know my json string is valid since it is working in the second code snippet and the value is being passed in the call. What else could I be missing?
Try this.
public class SearchParty
{
public string party { get; set; }
}
[HttpPost]
public ActionResult SearchInitiated(SearchParty party)
{
....
return View();
}
probably you need to set the traditional prop of jQuery.ajax to true in order to achieve traditional style of param serialization
put the below line of code immediatly after the document ready like
$(function(){
jQuery.ajaxSettings.traditional = true;
});
This SO question may help you further
I would make sure you have the [Serializable] attribute on your model. Also, make sure your request specifies party={myjson} .
You just need to declare a class 'SearchParty' in the controller to retrieve the strongly typed object in the controller without serializing.
public class SearchParty
{
public string party { get; set; }
}
public ActionResult SearchInitiated(SearchParty party)
{
code here....
}
Please check this link too
I resolved my error by modifying the javascript ajax call to this:
SearchPost(URL, JSON.stringify( {
'connectorId': '#Model.ConnectorId',
'sessionId': '#Model.SessionId',
'party' : currentSelectedParty
}))
I needed to stringify the entire data object sent in the ajax call, not just the 'party' object

MVC4 RC WebApi parameter binding

I upgraded from MVC4 beta to RC and the latest autofac. The following action was binding properly, but now both parameters are null. I see they changed things about the Formatters and such but I am not sure what caused my problem
[HttpPost]
RedirectModel MyAction(string value1, string value1)
REQUEST
Method: POST
Accept: application/json
URL: api/controller/myaction
BODY: {"value1":"1000", "value2":"foo"}
When you want to avoid using a DTO object, try this:
[HttpPost]
RedirectModel MyAction(dynamic value1, dynamic value2) {
string sValue1 = value1;
string sValue2 = value2;
Not really sure why the change from Beta, but I was able to make it work by changing the action signature to:
[HttpPost]
RedirectModel MyAction(MyActionDTO dto)
and defining MyActionDTO as
public class MyActionDTO
{
public string value1 { get; set; }
public string value2 { get; set; }
}
It was throwing an exception about not being able to bind to multiple body parameters using the two string paramaters. I guess using the DTO object more closely represents what you're sending in the AJAX call (a JSON object).

asp.net MVC 3 - reading POST payload in paramterized controller method

I had
[HttpPost]
public ActionResult Foo()
{
// read HTTP payload
var reqMemStream = new MemoryStream(HttpContext.Request.BinaryRead(HttpContext.Request.ContentLength));
....
}
The payload is application/json; worked fine; then I changed to
public ActionResult Foo(string thing)
{
....
}
The intention being to post to MyController/Foo?thing=yo
Now I cant read the payload(the length is correct but the stream is empty). My guess is that the controller plumbing has eaten the payload looking for form post data that can be mapped to the method parameters. Is there some way that I can stop this behavior (surely MVC should not have eaten a payload whose type is marked as JSON , it should only look at form post data). My work around is to add 'thing' to the json but I dont really like that
Try resetting the input stream position before reading:
public ActionResult Foo(string thing)
{
Request.InputStream.Position = 0;
var reqMemStream = new MemoryStream(HttpContext.Request.BinaryRead(HttpContext.Request.ContentLength));
....
}
Now this being said, if you are sending an application/json payload why on the holy Earth are you bothering to read directly the request stream instead of simply defining and using a view model:
public class MyViewModel
{
public string Thing { get; set; }
public string Foo { get; set; }
public string Bar { get; set; }
...
}
and then:
public ActionResult Foo(MyViewModel model)
{
// use the model here
....
}
ASP.NET MVC 3 has a built-in JsonValueProviderFactory which allows you to automatically bind JSON requests to models. And if you are using an older version it is trivially easy to add such factory your self as Phil Haack illustrates in his blog post.

Creating RESTful architecture to communicate between ASP.NET web app and MVC 3 App using JSON

I need to take GET fields from my asp.net web app (first name and last name). It needs to send that data from frontend(asp.net web app) using JSON to MVC 3 app. MVC 3 App would communicate with database, retrieve values and should serialize them into json object and POST to the front end(ASP.NET web app). Can anyone explain with a sample code how I would accomplish this?
You could use the WebClient class. It allows you to send HTTP requests to any web application. As far as the JSON part is concerned you will need a JSON serializer. You could use the built-in JavaScriptSerializer class or a third party such as Json.NET.
So let's suppose that you have the following controller action in your ASP.NET MVC 3 application that you want to invoke:
[HttpPost]
public ActionResult Foo(Bar bar)
{
...
return Json(new
{
status = "OK"
});
}
where the Bar class contains some properties (could be simple or complex types):
public class Bar
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Now you could invoke it like this from the client side:
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(new
{
firstName = "first",
lastName = "last"
});
var resultJson = client.UploadString("http://example.com/foo", json);
var result = serializer.Deserialize<Result>(resultJson);
}
where you would define the Result class to match the JSON structure returned by the application:
public class Result
{
public string Status { get; set; }
}

Resources