views:

311

answers:

2

I have a simple form that is used to update an entity in my ASP.NET MVC app. I want the user to be able to submit the form, have the proper Action on my controller be called and then notify the user that the update was completed.

Because I wanted to display a JQuery dialog after the user clicks the update button, I wanted to use JQuery to submit the form. However, my problem is this:

While I can easily get JQuery to call an action on my controller, I can't get it to call an action that I've already setup in my route and that has been decorated with [Authorize] and [AcceptVerbs(HttpVerbs.Post)]

For example, if the user is updating their entity at the following URL:

/SomeController/Edit/5

When JQuery submits the form, I want to submit it to my Edit Action that is already decorated and accepts the ID as a parameter.

The JQuery I am using to post the form is as follows:

$("#formFoo").submit(function() {
                var frm = $("#formFoo");
                var action = frm.attr("action");
                var serializedForm = frm.serialize();
                $.post(action, serializedForm, function() {
                    alert('Call completed');
                });
                return false;
            });

If I define my form as follows:

<form id="formFoo" action="/SomeController/SomeOtherAction" method="post">

and my Action as follows:

public void SomeOtherAction() 
{
    var myEntity=new MyEntity();
    UpdateModel(myEntity);
}

Then my action is called and my object is populated properly, but it's ID field isn't populated, so I don't know what entity I am updating.

If I change my form to:

<form id="formFoo" action="/SomeController/Edit" method="post">

and I have my Edit action defined as:

[Authorize,AcceptVerbs(HttpVerbs.Post)]
public void Edit(int id, FormCollection collection)

Then my action never seems to be called by JQuery.

I suppose I could somehow pull the ID parameter off of the querystring and stuff that into the data that I'm posting back to the form, but that seems very ugly. Or is there a way I can get the ID field while in in my SomeOtherAction action? Or am I just going about this all wrong?

+3  A: 

When you call:

$.post(action

Then the "action" argument needs to include the ID. In your question, you don't say what this is at runtime, but I strongly suspect it does not include the ID. Based on your sample URI for your Edit action, the ID should be in the path of the URI, not in the query. With the default MVC route it shouldn't make any difference, but without knowing what your routes are I would say that you should stick closely to the URI format that you give in the question.

So install firebug, if you haven't already, put a breakpoint in the JavaScript, and inspect the value of the action argument.

If it still looks right, open the Net panel of Firebug, click the XHR option, and look at the actual URI generated by your code. Make sure it is correct. If the URI is not correct, then look at your routes and make sure that this URI will be correctly routed to the right action.

Finally, but me that in a plug for the jQuery Ajax Form plug-in. I find that it makes this sort of thing very easy.

Craig Stuntz
I'm such a dolt. Of course! I just to add the ID field to the Action attribute of my Form. Thanks for the heads up! I tried that and it worked just fine.
Mark Hoffman
A: 

You have two ways to do this.

You can use FormCollection or use an entity.

The FormCollection sample:

  • Controller

    public ActionResult ProductEditHandle(int? productID, FormCollection formCollection) { Product product = null;

    if (productID.HasValue) product = ProductEditUpdateModel(productID.Value, formCollection);

    return View("ProductEdit", product); }

  • View

    <% using (Html.BeginForm("ProductEditHandle", "Product", new { productID = 5 })) { %> ...... <% } %>

The sample with entity:

  • Controller

    public ActionResult AddressTypeHandler(AddressTypeDto addressTypeDto) { var addressType = addressTypeDto.AddressTypeId > 0 ? _addressService.UpdateAddressType(addressTypeDto) : _addressService.CreateAddressType(addressTypeDto);

    return RedirectToAction("AddressTypeEdit", new { addressTypeId = addressType.AddressTypeId }); }

  • View (View declared with ViewPage - AddressTypeDto)

    <% using (Html.BeginForm("AddressTypeHandler", "People")) { %>

    <%= Html.Hidden("AddressTypeDto.AddressTypeId", (ViewData.Model != null) ? ViewData.Model.AddressTypeId : 0) %> <%=Html.TextBox("AddressTypeDto.Name", ViewData.Model != null ? ViewData.Model.Name : string.Empty, new { size = 50 })%> <% } %>

Hope this helps

alexl