I have a WebJob that is posting a JSON object to a controller in my MVC website.
The default ModelBinder is not working correctly in this instance. Rather than troubleshoot the binder, I am perfectly happy to handle the serialization myself.
How do I get the body of the POST request from my controller Action so that I can feed it into JSON.net?
I have tried using a StreamReader on Request.InputStream, but I get an empty string.
I'm using Angular.js $http.Post() to send a json object to my actionresult, and the Model Binding was failing. I used the below code and was able to get the json object posted and then use Newtonsoft for the DeSerialization. Interesting thing is that Newtonsoft didn't throw an error on Deserialization while the default model binding in MVC did.
var req = Request.InputStream;
var json = new StreamReader(req).ReadToEnd();
var result = JsonConvert.DeserializeObject<Model>(json);
Related
This question already has answers here:
Setting the default JSON serializer in ASP.NET MVC
(2 answers)
Closed 8 years ago.
I just solved a recent problem where Json.Net allows me to include the 'type' of an object when it serializes it going to the Client. The reason for this is that the class that I'm sending back and forth has a property that is typed as a BaseClass to 4 Subclasses. The great thing now is that my client is showing each one correctly with the type attribute on the Json.
Now I need to send the object back to my Controller, not to an API controller. I've seen a bunch of posts about the api controller using Json.Net as the default JsonFormatter, but this doesn't work for a regular MVC Controller.
So my question is....How can I get my Controller to use the Json.Net Serializer by default? And...will this cause an issue for other items potentially making ajax calls?
I was able to send my json back to my controller as a string and then use JsonConvert to Deserialize my object successfully, so I know it can be done.
Any thoughts are appreciated.
EDIT:
Ok, so I followed the instructions here to change out the JsonValueProviderFactory and that seems to be working, however its not helping the original issue.
The problem is that the JsonFormatter is still the old one and not using Json.Net. So the ProviderFactory is building the dictionary correctly, but when it tries to Deserialize my object, I'm only getting my properties cast as the BaseClass, and not the Derived Class that I'm expecting.
Thoughts on that part?
EDIT:
Simply...how do I create my own JsonNetMediaTypeFormatter in MVC4? I've changed the ProviderFactory, but that only changes how each individual parameter is serialized to its corresponding value. What I need to do is to use Json.Net so that my Parameters that are typed as a Hierarchy is serialized to the correct derived class...not typed as the Baseclass.
Edit - Last:
Ok...so I did verify that if I call an ApiController, it maps the incoming parameter with the correct subclass. So, I can go this route, but I'd really like to find a way to have the same result with my regular Controller.
I had the same issue and resolved it by simply overriding the Json method on my base controller class.
EX:
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
{
var result = new JsonNetResult
{
Data = data,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
return result;
}
I am developing an application using ASP.NET MVC 4 and it involves web API call where the result I am getting for a specific record is a Json string. I am doing this web API call inside an action method of a controller and the result I am getting for such call is in the following form:
result = "{\"fname\":\"John\",\"lname\":\"Doe\",\"empno\":123456,\"dept\":\"IT\"}"
I am new to MVC and Json and would really appreciate any help on how I can extract specific values from this Json string such as the value for dept?
Thanks.
In order to use this as an actual object in your project you will need to deserialize this string. .NET has it's own deserialization or you can check out Json.Net which is pretty simple to figure out. Check out the documentation on JsonConvert.DeserializeObject<>...
ie...
Instructor desInst = new Instructor();
responseContent = rsp.Content.ReadAsStringAsync().Result;
desInst = JsonConvert.DeserializeObject<Instructor>(responseContent);
I am getting some json data posted to my asp.net webapi, but the post parameter is always coming up null - the data is not being serialized correctly. The method looks something like this:
public HttpResponseMessage Post(string id, RegistrationData registerData)
It seems the problem is that the client (which I have no control over) is always sending the content-type as x-www-form-urlencoded, even though the content is actually json. This causes mvc to try to deserialize it as form data, which fails.
Is there any way to get webapi to always deserialize as json, and to ignore the content-type header?
I found the answer here: http://blog.cdeutsch.com/2012/08/force-content-types-to-json-in-net.html
This code needs to be added to Application_Start or WebApiConfig.Register
foreach (var mediaType in config.Formatters.FormUrlEncodedFormatter.SupportedMediaTypes)
{
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(mediaType);
}
config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
config.Formatters.Remove(config.Formatters.XmlFormatter);
It tells the json formatter to accept every type, and removes the form and xml formatters
I would suggest to rather modify the incoming request's content-type, let's say at the message handler to the appropriate content-type, rather than removing the formatters from config
I have an MVC project in which a controller action returns some JSON data (i.e. via /Home/GetData URL). This action also takes a custom object as a param.
This signature for the action is JsonResult GetData (MyCustomObject o)
I also have a client Silverlight project in which I'm constructing MyCustomObject and trying to call this URL (/Home/GetData/) via HttpWebRequest. However, I'm having trouble figuring out how to post in my object in this call. Do I need to serialize it to Json in order to pass it in?
Thanks so much!
MVC can accept and bind the submitted data to your MyCustomObject object, regardless of whether it is submitted as JSON, XML, a query string, a standard form POST, etc.
MVC does not require the object to be submitted in a particular fashion. That is up to you as the designer to determine what works best under the particular circumstances, given all of your requirements.
When submitted, MVC will use the ValueProvider suitable to the form of the data submitted, and the DefaultModelBinder will attempt to use the values in the ValueProvider to bind to your model.
Thanks for your help! Since the web app handles this with a getJSON call, I ended posting the object as a query string param i.e. I'm making a web request to http://../controller/action/view.aspx?custObject.property1=<value>&custObject.property2=<value> etc
I'm attempting to process the body of an HTTP PUT request, but it seems that the MVC engine (or perhaps the ASP.NET stack underpinning it) isn't automatically parsing & populating the request's Form collection with the body data.
This does work as expected when doing a POST.
Note that the request's InputStream property does contain the expected data, and obviously I can build my own key/value collection using that, however I would have expected PUT to work the same way as a POST.
Am I missing something here?
Example action method:
[AcceptVerbs(HttpVerbs.Put)]
public ActionResult Purchase(int id, FormCollection data)
{
// Do stuff with data, except the collection is empty (as is Request.Form)
}
Quote from the doc:
The Form collection retrieves the
values of form elements posted to the
HTTP request body, with a form using
the POST method.
So instead of using Request.Form I would recommend you writing a custom model class that will hold the request data and pass it as action parameter. The default model binder will automatically populate the properties from the key/values passed in the request stream:
[AcceptVerbs(HttpVerbs.Put)]
public ActionResult Purchase(MyCustomModel model)
{
// Do stuff with the model
}
Asp.net does not support PUT out of the box for custom requests. If you are using not the built in capabilities to generate the PUT url try adding X-HTTP-Method-Override with value of PUT in headers, form, or query string.