MVC form post not reaching controller - asp.net-mvc-3

I have a form that on submit doesn't reach the controller method (I put a breakpoint there)
[HttpPost]
public ActionResult SaveBilling( FormCollection fc )
{
...
}
the frontend code is something like this
<form action="/PersonSettings/SaveBilling" method="post" >
...
<input type='submit' value="save" />
</form>
any ideas ?
not sure if it is a route handler problem because it does reach the GET version if i go to /PersonSettings/SaveBilling in browser but the post method just yields a blank page and doesnt go into the code

Rewrite your view as:
#using (Html.BeginForm("SaveBilling", "PersonSettings", FormMethod.Post))
{
....
<input type='submit' value="save" />
}
Is this controller in any area or not?

I realize this has been solved, but I thought I'd tack on another possible cause: Having the [ValidateAntiForgeryToken] attribute on your method without an #Html.AntiForgeryToken() in your code will create the same problem.

Turns out it was a routing related issue after all , I have some complex routes and the default mvc route was catching things that should have gone through the default mvc route with areas.
Was able to recreate the issue by having explicit parameters for my function instead of a formcollection, so that might have been the issue ohwell.

use form and define action path.
<form id="subscriptionForm" action="/Category/Create" method="post">
--your div
</form >
Now use script to serialize the form
<script type="text/javascript">
$('#Save').click(function () {
var form = $("#subscriptionForm");
var url = form.attr("action");
var formData = form.serialize();
$.post(url, formData, function (data) {
$("#msg").html(data);
});
})
</script>
Now you can reach your controller action.

Sometimes using a network sniffing tool like Fiddler is helpful to see what's wrong when the request is sent and it seems not reaching the server.

Related

How to make Dojo as generic while submitting a form?

I have the following dojo (ver 1.9) code:
require(["dojo/dom", "dojo/on", "dojo/request", "dojo/dom-form"],
function(dom, on, request, domForm){
var form = dom.byId('user_login');
var selectedTabId = showIdOfSelectedTab();
// Attach the onsubmit event handler of the form
on(form, "submit", function(evt){
// prevent the page from navigating after submit
evt.stopPropagation();
evt.preventDefault();
// Post the data to the server
request.post("login1.php", {
// Send the username and password
data: domForm.toObject("user_login"),
// Wait 2 seconds for a response
timeout: 2000
}).then(function(response) {
dom.byId(selectedTabId).innerHTML = response;
});
});
}
);
And html below:
<form name="user_login" id="user_login">
User name: <input type="text" name="user_name" id="user_name" /><br />
Password: <input type="password" name="user_password" id="user_password" /><br />
<button id="submitbutton" name="submitbutton">Submit</button>
</form>
I want to make the above dojo code as generic by sending the post action (login1.php) and the form id (i.e., user_login). I tried several ways but I could not achieve it.
Please let me know if any of you have idea.
Thanks in advance.
-Uday
This is the demo drom the dojo Tutorial right?
http://dojotoolkit.org/documentation/tutorials/1.9/ajax/
Did you get any Errormessages?
So let's see.
Have you load the dojo libary correct? If not, the widgets can't be loaded.
Must be somthing like:
src="//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js">
Check the path to the login1.php.
If it's in another Folder than your code the path must be something like "../myfolder /myphp/login1.php"
Regards, Miriam

MVC3: Button action on the same view

i wish to change the inner html of a view on button click but maintain the view. I know how to change the html content of a div in javascript, but how can I have the action of the button not return a different view?
My buton looks like
<input type="submit" value="submit" onchange="myfunc()"/>
where myfunc() is the function in Javascript changing the div content.
Assuming you want a link to render content using ajax (and hopefully using razor) you can do something like the following:
First, setup the action to render the content partially. this can be done a few ways, but I'll keep with the logic in the action (and make it callable directly or by ajax):
[HttpPost]
public ActionResult Save(SomeModel model)
{
/* build view */
return Request.IsAjaxRequest() ? PartialView(model) : Wiew(model);
}
Next, setup a container in your page where the content will be populated along with the form you're looking to submit. If you want the form to disappear on a save, wrap it in the container. Otherwise, keep the container separated. In the below example, the from will submit and on success it'll come back, otherwise the new content will appear in its place:
<div id="ajaxContentPlaceholder">
#using (Ajax.BeginForm("Save", new AjaxOptions { UpdateTargetId = "ajaxContentPlaceholder" })) {
<!-- form elements -->
<input type="submit" value="save" />
}
</div>

Binding Model data to Knockout ViewModel?

Is it possible to bind data from your model to a knockout viewmodel. Heres an example:
public ActionResult Edit(int id)
{
Product product = _db.Products.FirstOrDefault(x=>x.ItemId == id);
return View(product);
}
Then in the View I would traditionally do something like so:
#model myApp.Models.Product
#using(Html.BeginForm())
{
#Html.EditorFor(x=>x.ItemName)
#Html.ValidationMessageFor(x=>x.ItemName)
<input type="submit" value="Update" />
}
But with Knockout I would create a EditProductViewModel from where I would do something like:
var EditProductViewModel = {
ItemName = ko.observable('')
};
EditProductViewModel.Edit = function() {
$.ajax({
url: "Home/Edit",
data: ko.ToJson(this),
success: function() {
// do something
}
});
};
$(function() {
ko.applyBindings(EditProductViewModel);
});
And instead of using the Html Helpers I would do something like so in my view:
<form data-bind="submit: Edit">
<input type="text" data-bind="value: ItemName" />
<input type="submit" value="Update" />
</form>
So how can I populate this with the data returned from my controller?
I don't have a any experience with knockout but it would seem to me that you would no longer want to return a view from your controller how about
return JSON(product)
that way you would get a json element of the product on your javascript success function you would need to collected the json element
$.ajax({
url: "Home/Edit",
data: ko.ToJson(this),
success: function(data) {
// map to knockout view model
}
});
and then from here you would call the map bindings.
When using knockout you have two ways to do this.
1. Load your textboxes, etc in one view. Upon loading that view for the first time convert your model to JSON upon in initial load to use by knockout.
ALL additional calls to/from go via JSON.
You can use in your View:
#Html.Raw(Json.Encode(yourModel))
Load your textboxes in your view (ie they are part of your vieW)
Trigger off on document.ready() your ajax calls to get your data from your controller, convert to JSON ie return Json(yourModel, JsonRequestBehavior.AllowGet) and bind those results roughly as you are already doing above
Note - the downside with this approach is with validation. If you have all client side validation, then this is OK as the attributes for data-* will have been written out by MVC to your textboxes, etc. If you have any server side validation, there is no 'smooth' built in integration here with knockout.
There's a decent article here:
http://www.codeproject.com/Articles/305308/MVC-Techniques-with-JQuery-JSON-Knockout-and-Cshar
but still lacks on server side validation mention.
You could serialize data to your page and then initialize knockout viewmodel with values from server.
ItemName = ko.observable(serializedModel.ItemName);

How can I use multiple ajax forms with AntiForgery validation on the same MVC3 page?

When we have more than one possible form to post to the controller on the same cshtml page,
the Antiforgery validation does not work. We went through the MVC3 code and we found the problem is in this part of the code:
if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
// error: form token does not match cookie token
throw CreateValidationException();
}
The cshtml that we have is something like this:
#using (#Ajax.BeginForm()) {
#Html.AntiForgeryToken()
<input type="submit" class="buttonBlue" value="form1" />
}
#using (#Ajax.BeginForm()) {
#Html.AntiForgeryToken()
<input type="submit" class="buttonBlue" value="form2" />
}
Can you help me to fix this issue? We found that after removing one of the antiforgery tokens eveyrthing seems to work as expected.
We tried setting the machine key for the antiforgery and it didn't work either.
Regards.
In order to use the AntiForgeryToken multiple times, I do the following. First, at the top of my view, I add the following line:
ViewBag.__RequestVerificationToken = #Html.AntiForgeryToken().ToString();
Then, in each form where I need the token, I add the following:
#Html.Raw(ViewBag.__RequestVerificationToken)

MVC3 strange hidden value missing during PartialView Ajax Call

I'm having a very strange issue when rendering a partial view. My page has a table whose rows are rendered using a partial view. Here's a snippet
<td>
<img src="#Url.Content("~/Content/Images/edit_icon.gif")" class="editLine" />
<img src="#Url.Content("~/Content/Images/delete_icon.gif")" class="deleteLine" />
#Html.HiddenFor(model => model.LineId)
</td>
This renders fine when the page first loads. The input tags have the value set to the id. However, when I do an ajax call and return the PartialView from the controller, this value is always 0.
Controller code:
line.LineId = 12; //whatever the actual value is
return PartialView("Line", line);
And the jquery code is
$.ajax({
data: {
Id: id
},
success: function (data, textStatus) {
$('#lines').append(data);
}
When I debug through and look I see data has come back as
<input name="lineId" id="lineId" value="0" />
I debugged through EVERYTHING and the lineId is not 0. I then debugged throuh the view itself and whenever I did Html.Hidden("lineId", anyvalueHere) it rendered as 0. When I changed it to be Html.Hidden("lineId_" + actualId, actualId) it worked.
Is this known/expected behavior? I can imagine it not jiving with duplicate id's. However, it renders just fine on the page load where I use the exact same partial view. Is there magical juju for client side stuff? I would imagine not since it's just a controller action and it doesn't know the difference. Has anyone seen this. Thanks
If you are changing the value when you post, that is the issue. Use:
<input type='hidden' name='LineId' value='<%: Model.LineId %>'/>
instead of the Html.HiddenFor.

Resources