what is Request.InputStream and when to use it? - asp.net-mvc

Question is really simple. What is Request.InputStream and when to use it. Is it always used to read entire html body sent in the post request or only some parameters sent in it? Why should i not send data as a parameter to my server side code by passing it in the Ajax request?
In the example i can either pass the parameter in the data: or i can read the parameter in the Request.InputStream. When should i use which one?
Example:
In controller:
public ActionResult GetSomeData(string someData)
{
Request.InputStream.Position = 0;
System.IO.StreamReader str = new System.IO.StreamReader(Request.InputStream);
string sBuf = str.ReadToEnd();
return Json("something");
}
Ajax Request:
$.ajax({
type: "POST",
url: "Home/GetSomeData",
data: "{someData:'Hello'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert(msg);
// Insert the returned HTML into the <div>.
$('#dvResult').html(msg);
}
});

Request.InputStream allows you to access the raw request data. If this data is formatted using some standard format such as application/x-www-form-urlencoded or multipart/form-data or some other format that the default model binder understands you do not need to use Request.InputStream. ASP.NET will parse the request values and you will be able to access them directly using Request[...]. Of course in ASP.NET MVC you don't even need to use Request[...] because you can define a view model which your controller action will take as parameter and leave the model binder assign its properties from the request.
There are cases though when you might want to access the raw request stream. For example you have invented some custom protocol and the client sends some custom formatted data in the request stream. Those cases are very rare since inventing custom protocols is not very common.
Now back to your question. In your case you could define a view model:
public class MyViewModel
{
public string SomeData { get; set; }
}
which your controller action will take as argument:
public ActionResult GetSomeData(MyViewModel model)
{
// model.SomeData will contain the Hello string that the client sent
return Json("something");
}
and on the client I would recommend you using the JSON.stringify method which is natively built into modern browsers to JSON serialize the request javascript literal into a JSON string instead of manually writing the JSON as you did:
$.ajax({
type: 'POST',
url: 'Home/GetSomeData',
data: JSON.stringify({ someData: 'Hello' }),
contentType: 'application/json; charset=utf-8',
success: function (msg) {
alert(msg);
// Insert the returned HTML into the <div>.
$('#dvResult').html(msg);
}
});

Related

MVC Controller not parsing Ajax Request Correctly?

I have an MVC .NET 4.5 application using an Ajax request with JSON to hit the MVC controller on server side. The function in the controller looks like this:
[HttpPost]
public void SomeFunction(int int1, List<int> listOfInts, int int2)
{
someOtherFunction(int1, listOfInts, int2);
}
and the ajax request looks like this:
actionData = {
int1: 1,
int2: 2,
listOfInts: list
}
$.ajax({
type: 'POST',
url: actionURL,
data: JSON.stringify(actionData),
traditional: true,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: functionIfSuccessful() },
error: functionIfNotSuccessful() }
});
If I look at the request in Fiddler the JSON ojbect being passed has the format:
int1=1
int2=2
listOfInts=[1,2]
The problem is when the function in the MVC controller is hit, the int1 and int2 properties are set correctly from the request but the listOfInts parameter is empty. I have tried changing it to use a primitive array instead of a List object aswell but that didn't change anything.
Fixed. This issue was being caused by something outside of the code provided. The javascript that was building the list of integers should not have been adding the brackets to the ends. Removed those and it worked like a charm.

MVC Controller return Content instead of JSON

I've been working on a project were all of my requirements involved JSON. However now suddenly I have a need to return results from my model that can be used in an input elements value field. I can't use the solution I have been as I get objects returned instead of plain text for the value. This is the controller pattern I have been using:
public virtual JsonResult fooData()
{
var fooresults = new fooQueries().fooTotal();
return new JsonResult
{ JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = fooresults };
}
Is there a way to use return content instead of JsonResult? I'm fairly new to the .NET MVC framework and having some difficulty finding the correct way to do this.
My current results are formatted like this:
[{ "foo", 3 }]
Instead I would prefer to get plain text so that I can use an AJAX request to pass the 3 value into an input elements value="" field.
AJAX call I am using with the controller:
$.ajax({
type: 'GET',
url: $('#fooValue').data('url'),
success: function (data) {
$('#fooValue').val(data);
}
});
The data-url is equivalent to:
../fooController/fooData
I'm just using T4MVC.
Return a ContentResult instead of a JsonResult
public virtual ContentResult gooData()
{
var fooresults = new fooQueries().fooTotal();
return Content(fooresults);
}
You can return content as:
return Content(fooresults);
But this wont be clean to you separate the elements as JSON return is.
I'm not sure what the shape of fooresults is, but you should be able to alter your AJAX call to the following:
$.ajax({
type: 'GET',
url: $('#fooValue').data('url'),
success: function (data) {
$('#fooValue').val(data.foo);
}
});
If the dataType property of the jQuery ajax call isn't explictly set, then jQuery will try and infer the type of the return result based on the MIME type, which in your case will be JSON. Therefore jQuery will deserialise the JSON to a JSON object. See http://api.jquery.com/jQuery.ajax/ for more info.
to return a Json, the method should be changed as follow:
public JsonResult fooData()
{
var fooresults = new fooQueries().fooTotal();
return Json(fooresults , JsonRequestBehavior.AllowGet);
}

asp.net mvc 3 json values not recieving at controller

the problem is that i am not able to recieve any value in the controller . what could be wrong? the code is here.
$('#save').click(function () {
var UserLoginViewModel = { UserName: $('vcr_UserName').val(),
Password: $('vcr_Password').val()
};
$.ajax({
url: "/User/Login",
data: JSON.stringify(UserLoginViewModel),
contenttype: "application/json; charset=utf-8",
success: function (mydata) {
$("#message").html("Login");
},
error: function () {
$("#message").html("error");
},
type: "POST",
datatype: "json"
});
return false;
});
});
[HttpPost]
public ActionResult Login(UserLoginViewModel UserLoginViewModel)
{
}
As you're using MVC3 - you should be able to take advantage of the built in JSON model binding.
Your code example has a couple of typos: contentType and dataType are lowercase...(they should have an uppercase "T")
jQuery ajax docs
After you POST up the correct contentType/dataType, MVC should automatically bind your object to the posted JSON.
You're going to need an action filter or similar to intercept the json from the post body.
Here's a starter
Provider Factory
but here is the article that sorted this for me On Haacked
It is good if you know the type you are deserialising into up front, but if you need polymorphism you'll end up using these ideas in an action filter.

MVC ajax json post to controller action method

I am trying to achieve a JQuery AJAX call to a controller action method that contains a complex object as a parameter.
I have read plenty blogs and tried several techniques learned from these. The key post on which I have constructed my best attempt code (below) is the stackoverflow post here .
I want to trigger an asynchronous post, invoked when the user tabs off a field [not a Form save post – as demonstrated in other examples I have found].
My intention is to:
Instantiate an object on the client [not the ViewModel which provides the type for the View];
Populate the object with data from several fields in the view;
Convert this object to JSON;
Call the controller action method using the jQuery.Ajax method, passing the JSON object.
The results will be returned as a JSON result; and data will be loaded into fields in the view depending on results returned.
The problems are:
If the action method is attributed with the HttpPost attribute, the controller Action method is not invoked (even though the AJAX call type is set to ‘POST’).
If the action method isattributed with HttpGet, the values of properties of the parameter are null
The ReadObject method throws the error: "Expecting element 'root' from namespace ''.. Encountered 'None' with name 'namespace'".
Hopefully someone can help. Thanks. Code below:
Client js file
var disputeKeyDataObj = {
"InvoiceNumber": "" + $.trim(this.value) + "",
"CustomerNumber": "" + $.trim($('#CustomerNumber').val()) + ""
};
var disputeKeyDataJSON = JSON.stringify(disputeHeadlineData);
$.ajax({
url: "/cnr/GetDataForInvoiceNumber",
type: "POST",
data: disputeKeyDataJSON,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: EnrichedDisputeKeyData(result)
});
Action Filter and class for the type associated with the Action method parameter
[DataContract]
public class DisputeKeyData
{
[DataMember(Name = "InvoiceNumber")]
public string InvoiceNumber { get; set; }
[DataMember(Name = "CustomerNumber")]
public string CustomerNumber { get; set; }
}
Action method on the controller
//[HttpPost]
[ObjectFilter(Param = "disputeKeyData", RootType = typeof(DisputeKeyData))]
public ActionResult GetDataForInvoiceNumber(DisputeKeyData disputeKeyData)
{
//Blah!
//....
return Json(disputeKeyData, JsonRequestBehavior.AllowGet);
}
Below is how I got this working.
The Key point was:
I needed to use the ViewModel associated with the view in order for the runtime to be able to resolve the object in the request.
[I know that that there is a way to bind an object other than the default ViewModel object but ended up simply populating the necessary properties for my needs as I could not get it to work]
[HttpPost]
public ActionResult GetDataForInvoiceNumber(MyViewModel myViewModel)
{
var invoiceNumberQueryResult = _viewModelBuilder.HydrateMyViewModelGivenInvoiceDetail(myViewModel.InvoiceNumber, myViewModel.SelectedCompanyCode);
return Json(invoiceNumberQueryResult, JsonRequestBehavior.DenyGet);
}
The JQuery script used to call this action method:
var requestData = {
InvoiceNumber: $.trim(this.value),
SelectedCompanyCode: $.trim($('#SelectedCompanyCode').val())
};
$.ajax({
url: '/en/myController/GetDataForInvoiceNumber',
type: 'POST',
data: JSON.stringify(requestData),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
success: function (result) {
CheckIfInvoiceFound(result);
},
async: true,
processData: false
});

How to send a model in jQuery $.ajax() post request to MVC controller method

In doing an auto-refresh using the following code, I assumed that when I do a post, the model will automatically sent to the controller:
$.ajax({
url: '<%=Url.Action("ModelPage")%>',
type: "POST",
//data: ??????
success: function(result) {
$("div#updatePane").html(result);
},
complete: function() {
$('form').onsubmit({ preventDefault: function() { } });
}
});
Every time there is a post, I need to increment the value attribute in the model:
public ActionResult Modelpage(MyModel model)
{
model.value = model.value + 1;
return PartialView("ModelPartialView", this.ViewData);
}
But the model is not passed to the controller when the page is posted with jQuery AJAX request. How can I send the model in the AJAX request?
The simple answer (in MVC 3 onwards, maybe even 2) is you don't have to do anything special.
As long as your JSON parameters match the model, MVC is smart enough to construct a new object from the parameters you give it. The parameters that aren't there are just defaulted.
For example, the Javascript:
var values =
{
"Name": "Chris",
"Color": "Green"
}
$.post("#Url.Action("Update")",values,function(data)
{
// do stuff;
});
The model:
public class UserModel
{
public string Name { get;set; }
public string Color { get;set; }
public IEnumerable<string> Contacts { get;set; }
}
The controller:
public ActionResult Update(UserModel model)
{
// do something with the model
return Json(new { success = true });
}
If you need to send the FULL model to the controller, you first need the model to be available to your javascript code.
In our app, we do this with an extension method:
public static class JsonExtensions
{
public static string ToJson(this Object obj)
{
return new JavaScriptSerializer().Serialize(obj);
}
}
On the view, we use it to render the model:
<script type="javascript">
var model = <%= Model.ToJson() %>
</script>
You can then pass the model variable into your $.ajax call.
I have an MVC page that submits JSON of selected values from a group of radio buttons.
I use:
var dataArray = $.makeArray($("input[type=radio]").serializeArray());
To make an array of their names and values. Then I convert it to JSON with:
var json = $.toJSON(dataArray)
and then post it with jQuery's ajax() to the MVC controller
$.ajax({
url: "/Rounding.aspx/Round/" + $("#OfferId").val(),
type: 'POST',
dataType: 'html',
data: json,
contentType: 'application/json; charset=utf-8',
beforeSend: doSubmitBeforeSend,
complete: doSubmitComplete,
success: doSubmitSuccess});
Which sends the data across as native JSON data.
You can then capture the response stream and de-serialize it into the native C#/VB.net object and manipulate it in your controller.
To automate this process in a lovely, low maintenance way, I advise reading this entry that spells out most of native, automatic JSON de-serialization quite well.
Match your JSON object to match your model and the linked process below should automatically deserialize the data into your controller. It's works wonderfully for me.
Article on MVC JSON deserialization
This can be done by building a javascript object to match your mvc model. The names of the javascript properties have to match exactly to the mvc model or else the autobind won't happen on the post. Once you have your model on the server side you can then manipulate it and store the data to the database.
I am achieving this either by a double click event on a grid row or click event on a button of some sort.
#model TestProject.Models.TestModel
<script>
function testButton_Click(){
var javaModel ={
ModelId: '#Model.TestId',
CreatedDate: '#Model.CreatedDate.ToShortDateString()',
TestDescription: '#Model.TestDescription',
//Here I am using a Kendo editor and I want to bind the text value to my javascript
//object. This may be different for you depending on what controls you use.
TestStatus: ($('#StatusTextBox'))[0].value,
TestType: '#Model.TestType'
}
//Now I did for some reason have some trouble passing the ENUM id of a Kendo ComboBox
//selected value. This puzzled me due to the conversion to Json object in the Ajax call.
//By parsing the Type to an int this worked.
javaModel.TestType = parseInt(javaModel.TestType);
$.ajax({
//This is where you want to post to.
url:'#Url.Action("TestModelUpdate","TestController")',
async:true,
type:"POST",
contentType: 'application/json',
dataType:"json",
data: JSON.stringify(javaModel)
});
}
</script>
//This is your controller action on the server, and it will autobind your values
//to the newTestModel on post.
[HttpPost]
public ActionResult TestModelUpdate(TestModel newTestModel)
{
TestModel.UpdateTestModel(newTestModel);
return //do some return action;
}
I think you need to explicitly pass the data attribute. One way to do this is to use the
data = $('#your-form-id').serialize();
This post may be helpful.
Post with jquery and ajax
Have a look at the doc here..
Ajax serialize
you can create a variable and send to ajax.
var m = { "Value": #Model.Value }
$.ajax({
url: '<%=Url.Action("ModelPage")%>',
type: "POST",
data: m,
success: function(result) {
$("div#updatePane").html(result);
},
complete: function() {
$('form').onsubmit({ preventDefault: function() { } });
}
});
All of model's field must bo ceated in m.
In ajax call mention-
data:MakeModel(),
use the below function to bind data to model
function MakeModel() {
var MyModel = {};
MyModel.value = $('#input element id').val() or your value;
return JSON.stringify(MyModel);
}
Attach [HttpPost] attribute to your controller action
on POST this data will get available

Resources