I have an ajax POST request that is supposed to be submitting data to an ASP.NET MVC action. This works fine 95% of the time but every so often, for whatever reason, my FormCollection is empty and the application errors out as a result.
I would have included the raw request values however I haven't been able to reproduce this myself.
My ajax call looks like this:
var data = {};
data.Property = 123; // etc
$.ajax({
url: url,
type: 'POST',
dataType: 'json',
data: JSON.stringify(data),
success: function(viewModel) {
// do stuff
}
});
What would cause the FormCollection to intermittently be empty on the ajax POST?
I have suspected things like session timeouts and the like but I would expect that to error out before I get in to the action.
First of all you seem to be sending a JSON request (JSON.stringify(data)). This is not supported out of the box in ASP.NET MVC 2. It is in ASP.NET MVC 3 that a JsonValueProviderFactory was introduced. You may take a look at the following article which explains in more details JSON requests in ASP.NET MVC.
Also everytime you want to send a JSON request you should set the proper content type using the contentType parameter:
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
and last but not least I would recommend you to use view models instead of relying on some weakly typed structures such as FormCollection in your controller actions and having to write plumbing code.
UPDATE:
FormCollection is a key/value pair collection. So if you want to use it (despite my recommendation against it) you should not use a JSON request. You should use a normal key value request. So remove the JSON.stringify from your AJAX request and remove the contentType: 'application/json' parameter as well. There's really no point in using weakly typed key/value pair collection with JSON objects.
Related
I am teaching myself asp.net mvc4, and I wounder if I could pass an asp.net Model to an action method by jquery/ajax function
Yes, you can.
On the Javascript side of things, generate a JSON and send it to your Action method.
On this method, you just Deserialize it back to a Model object using, for example, Json.NET.
Oh the other way round, you can just Serialize the Model object into a JSON.
http://json.codeplex.com/
In ASP.NET MVC 4 you dont actually "pass" the model to the action method. If you do a form submit the model values will automatically be available to you in the action.
If you want to explicitly call the action in an ajax method then you can pass the individual values as JSON.
U can do it as follows,
$.ajax({
type: "POST",
url: "Home/Insert", // Your URL
data: JSON.stringify(model),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
},
error: function () {
}
});
I have a web application that uses VB.NET MVC for the server side code. I set up the client side JavaScript to easily send and receive data to the server Controller functions. Basically what I did was create a JavaScript "request" object that uses Ajax to call a controller function and pass in parameters. I let MVC do all of the serialization for me. Then the controller function returns a JSON, usually with a block of HTML as a string. Since I am handling all of the ajax calls in one place, I can't figure out a good way to handle the responses. When the ajax response comes back, I have no way of knowing which request it came from. The website has a lot going on so the responses all need to be handled differently and all return different data.
Right now what I do is in the controller function I send back some key along with the block of HTML, then in the ajax complete function I check for all of these specific keys. Doing it this way makes the javascript code difficult to manage.
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
if (data.Foo) {
Foo(data);
} else if(data.Bar) }
Bar(data);
}
});
I am having trouble researching this because I don't know which keywords to look up. I think I'm going to try and do something where I call the function names dynamically in the ajax done function, but I was wondering if there are any existing libraries or code examples that do larger scale ajax request functions like this.
Maybe the problem comes from the idea of "doing all the stuff in one place". I can imagine that it will be very difficult to maintain your code once you have 40 chained if...else if... in one method. Maybe splitting things up a bit wont hurt after all.
Anyway, one way of doing it the way you want it would be instead of passing a key, passing the name of the javascript function as a delegate. Then call window[data.funcName](data); in done().
Say your json is
{
foo: "bar",
funcName: "DoMyFoo"
}
This is how your call would look like :
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
window[data.funcName](data);
});
function DoMyFoo(d){
//Do your specific stuff here
alert(d.foo);
}
See this question How to execute a JavaScript function when I have its name as a string for info and examples.
Edit: If your functions lies within an object instance instead of the global namespace, say obj, you can call it the same way with obj['myFunction'](args)
While there appears to be similar questions I do not believe I found one where somebody was passing the entire model from view to controller, the closest I found was passing a data value in the model to the controller... which is not what I want to do...
I want to pass the model object to the applicable controller action result as a parameter
and do what I want to do with the data in the model object from within the controller...
code abbreviated...
in the view i am using Url.Action(string, string, object) to pass the controller method name, and the route to it as the 2nd parameter, and the entire model object as the 3rd parameter...
my third parameter is the problem, the Url.Action(string, string) over load works fine with the same values, so I don't have any problem getting to the controller action result method, with the values I am using...
view code snippet...
$('#ControllerActionResult').click(function (e) {
window.location = '<%: Url.Action("ControllerActionResult", TheRoute, new { pModel = Model } ) %>';
});
controller code snippet...
public ActionResult ControllerActionResult(object pModel)
{
}
My error is "CS1502: The best overloaded method match for 'System.Web.Mvc.UrlHelper.Action(string, string, object)' has some invalid arguments" and the window location line is highlighted...
Am I missing something obvious?
I don't think you can do that. Url is trying to build a url, not call the action method directly. You can pass individual key value pairs via the anonymous object, which Url can then use to build a link. Model binding can take care of putting the key value pairs into the incoming model for you.
Also, is TheRoute a string as well?
If you need a Url you don't have many alternatives. Either pass all the values to rebuild the model, or just pass a key value to retreive the model from the database again (or maybe session / viewdata / tempdata, if you're using that).
There might be several issues in your code. But I will answer what you want to know, how to send data to controller from js. You have to first send "model" in json format, possibly with jquery.ajax. For example,
$.ajax({
url: '#Url.Action("ControllerActionResult")',
type: 'POST',
data: JSON.stringify(model),
dataType: 'json',
processData: false,
contentType: 'application/json; charset=utf-8',
success: OnSuccess
});
In controller, you have to have a defined class for the "model" and that should be the parameter of your controller.
[HttpPost]
public ActionResult ControllerActionResult(Model model) {
if (Request.IsAjaxRequest()) {
//to do
}
}
Otherwise, MVC cannot find a right controller to call.
try with following code it works for me
Javascript:
var location ='#url,action(string ,obj)'; window.location=location;
Controller:
public ActionResult index(string obj){return view();}
hope this works for you.
I inherited an MVC app and am a true novice at it coming from an ASP.NET environment. My problem is I can't manage to move variable data between my partial views and controllers. In ASP.NET this was pretty straight forward, not the case in MVC. So the following code fires when a Tab is selected from the client but I need to capture the selectedTabIndex value from the client and pass it to the controller.
function onTabSelect(e) {
var selectedTabIndex = 0;
selectedTabIndex = $(e.item).index();
alert(selectedTabIndex);
}
I considered using the ViewData object but there doesn't appear to be a way to make perform this task of assignment from within the function. So the following code would seem to be a ridiculous task and it fails anyway. (Remember, I am an extreme novice at this)
function onTabSelect(e) {
var selectedTabIndex = 0;
<% =ViewData["selectedTabIndex"]%> = selectedTabIndex;
}
I also considered using cookies but that doesn't seem to be a practical method either. In ASP.NET I could access the client controls using the .find method but this is a steep learning curve for me.
What are my alternatives?
If different tabs can be selected by the user between Save operations, you might need to consider binding some kind of click function (using jQuery) to set the selectedTabIndex javascript variable. Alternatively, you could set a hidden input's value to the selected tab index.
In either case, if you need the value in your controller (to set ViewData, ViewBag, some model data, etc) when a Save operation is submitted, you could submit the data via $.ajax and return some JSON from your controller
$('#SaveButton').click(function() {
$.ajax({
url: '/Controller/Save',
type: 'POST',
// you might need to serialize additional data you want to save here
// but you could create any JSON object before calling $.ajax
data: {"selectedTabIndex": selectedTabIndex}, // data to POST
dataType: 'json', // this indicates the type of data returned from controller
success: function(data) {
// you didn't really describe how to programatically set a tab,
// so "setToTab" is a guess
$('#tabID').setToTab(data.selectedTabIndex);
}
});
}
And your controller might look something like
public ActionResult Save(int selectedTabIndex)
{
// again, you might need different parameters to complete your Save
return JsonResult(new { selectedTabIndex: selectedTabIndex });
}
Data is sent to a controller via a HTTP POST. Create a hidden input <input type="hidden" name="selectedTabIndex"/> and set the value with javascript prior to POST. The controller can extract this value from the Form parameters, or it can be autopopulated in the Action method if the method contains a parameter matching the input name.
This is a non-ajax alternative to the answer provided by David.
I have no problems processing jQuery GET requests in a controller, however I cannot get any form data to POST. The client snippet
$.post(url,{name:"John"},function(result){
//process result
});
combined with a controller,
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Save(string name)
{
return Json("Success!");
}
will result in a NULL value for the name parameter when inspected inside the action method, whereas I expected name to be mapped to the method parameter. Also all other objects (Request.Form), etc. in this context seem to be NULL. I can do this with a $.get, but I think I am supposed to do any operations with side-effects with POSTs. I am using ASP.NET MVC 1.0, jQuery 1.2.6 and Internet Explorer 7.
Thanks!
Update: see my answer below and humble apologies
Sorry guys, I had a $.ajaxSetup entry in the page which overrided the default contentType to application/json.
When using the default contentType as follows:
$.ajax({ url,
type: "POST",
contentType: "application/x-www-form-urlencoded",
success: function(result) { alert(result); },
data: { name: "John" }
});
It works because processData is true by default which means the data entry with the JSON object will be parsed into a string (data: "name=John" also works).
Sorry for wasting your time :) and thanks to Mark for the suggestion on passing JSON objects, ill do that next cause it seems very cool.
I believe your code should work, is your URL correct and your routes setup correctly? In addition you could always fire up Fiddler to see exactly what your request to the server is and if you are passing the correct items.
Could it be that the Save(string name) method is expecting stringified JSON? Try this:
$.post(url,
"{'name':'John'}", function(result){
});
It isn't so simple as making a json object and throwing it at an action.
Start from here. People have written small scripts that get the JSON object dressed and ready for an action to read it in and map it to properties or arguments.