Asp.net-mvc – ASP.NET MVC Passing Data from View to Controller

asp.net-mvc

I have a view with a grid that contains items added to a workstation. The user can select an item from a drop down list and click an action link which calls a controller that adds that item to the workstation. I can make it work by reading the FormCollection object in the Post action of the controller.

<p>
    <% using(Html.BeginForm("AddItem", "Home")) { %>
    <label for="ItemID">Item:</label>
    <%= Html.DropDownList("ItemID", Model.ItemsList) %>
    <%= Html.Hidden("WorkstationID", Model.Workstation.RecordID) %>
    <input type="submit" value="Submit" />
    <% } %>
</p>

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddItem(FormCollection formValue)
{
    long workstationId = Convert.ToInt64(formValue["WorkstationID"]);
    long itemId = Convert.ToInt64(formValue["ItemID"]);

    Workstation workstation = itilRepository.FindWorkstation(workstationId);
    Item item = itilRepository.FindItem(itemId);

    itilRepository.AddItem(workstation, item);
    itilRepository.Save();

    return Content("Item added successfully!");
}

What I want to do is be able to submit the two parameters the workstationId and itemId to the controller using Ajax.ActionLink and have the new item that was added get inserted into the grid. I am rendering the grid like this:

<table>
      <tr>
        <th></th>
      <th>
        Name
      </th>
      <th>
        Service Tag
      </th>
      <th>
        Serial Number
      </th>
    </tr>

    <% foreach (var item in Model.Items) { %>

    <tr>
      <td>
        <%= Html.ActionLink("Edit", "ItemEdit", new { id = item.RecordID }) %> |
        <%= Html.ActionLink("Details", "ItemDetails", new { id = item.RecordID   })%>
      </td>
      <td>
        <%= Html.Encode(item.Name) %>
      </td>
      <td>
        <%= Html.Encode(item.ServiceTag) %>
      </td>
      <td>
        <%= Html.Encode(item.SerialNumber) %>
      </td>
    </tr>

    <% } %>

</table>

The problem I have is when I submit using the ActionLink I can't figure out how to pass in the parameters to the controller and how to update the grid without reloading the entire view.

I would really appreciate some help with this or even a link to a tutorials that does something similar.

Thank You!

This is the working version, the one problem is that when the controller returns the partial view that is all that gets rendred the actual page is gone.

<% using (Ajax.BeginForm("AddItem", null, 
        new AjaxOptions
        {
            UpdateTargetId = "ResultsGoHere",
            InsertionMode = InsertionMode.Replace
        }, 
        new { @id = "itemForm" } ))
{ %>

    <label for="ItemID">Item:</label>
    <%= Html.DropDownList("itemId", Model.ItemsList) %>
    <%= Html.Hidden("workstationId", Model.Workstation.RecordID) %>

    <a href="#" onclick="$('#itemForm').submit();">Submit</a>

    <div id="ResultsGoHere">
        <% Html.RenderPartial("WorkstationItems", Model.Items); %>
    </div>

<% } %>

Not sure what the cause is, the replace was working correctly before but the controller wasn't getting the drop down value. Now the controller is getting the value but the partial view that is returned replaces the entire page.

The Action Method:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddItem(string workstationId, string itemId)
{
    long lworkstationId = Convert.ToInt64(workstationId);
    long litemId = Convert.ToInt64(itemId);

    Workstation workstation = itilRepository.FindWorkstation(lworkstationId);
    Item item = itilRepository.FindItem(litemId);

    IQueryable<Item> items = itilRepository.AddItem(workstation, item);
    itilRepository.Save();

    return PartialView("WorkstationItems", items);
}

This is the HTML for the View that does all the work:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ITILDatabase.Models.WorkstationFormViewModel>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Workstation Details
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
    <link type="text/css" href="/../Content/css/ui-lightness/jquery-ui-1.7.2.custom.css" rel="stylesheet" />    
    <script type="text/javascript" src="/../Content/js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="/../Content/js/jquery-ui-1.7.2.custom.min.js"></script>

    <h2>
        Workstation Details</h2>
    <fieldset>
        <legend>Fields</legend>
        <p>
            Record ID:
            <%= Html.Encode(Model.Workstation.RecordID) %>
        </p>
        <p>
            Name:
            <%= Html.Encode(Model.Workstation.Name) %>
        </p>
        <p>
            Description:
            <%= Html.Encode(Model.Workstation.Description) %>
        </p>
        <p>
            Site:
            <%= Html.Encode(Model.Workstation.Site.Name) %>
        </p>
        <p>
            Modified By:
            <%= Html.Encode(Model.Workstation.ModifiedBy) %>
        </p>
        <p>
            Modified On:
            <%= Html.Encode(String.Format("{0:g}", Model.Workstation.ModifiedOn)) %>
        </p>
        <p>
            Created By:
            <%= Html.Encode(Model.Workstation.CreatedBy) %>
        </p>
        <p>
            Created On:
            <%= Html.Encode(String.Format("{0:g}", Model.Workstation.CreatedOn)) %>
        </p>
    </fieldset>
    <fieldset>
        <legend>People</legend>
        <% Html.RenderPartial("WorkstationPeople", Model.People); %>
    </fieldset>
    <fieldset>
        <legend>Positions</legend>
        <% Html.RenderPartial("WorkstationPositions", Model.Positions); %>
    </fieldset>
    <fieldset>
        <legend>Items</legend>

            <% using (Ajax.BeginForm("AddItem", "Home", null, 
                    new AjaxOptions
                    {
                        UpdateTargetId = "ResultsGoHere",
                        InsertionMode = InsertionMode.Replace
                    }, 
                    new { @id = "itemForm" } ))
            { %>

                <label for="ItemID">Item:</label>
                <%= Html.DropDownList("itemId", Model.ItemsList) %>
                <%= Html.Hidden("workstationId", Model.Workstation.RecordID) %>

                <a href="#" onclick="$('#itemForm').submit();">Submit</a>

                <div id="ResultsGoHere">
                    <% Html.RenderPartial("WorkstationItems", Model.Items); %>
                </div>

            <% } %>
    </fieldset>
    <br />
    <p>
        <%=Html.ActionLink("Edit", "WorkstationEdit", new { id = Model.Workstation.RecordID }) %>
        |
        <%=Html.ActionLink("Back to List", "Index") %>
    </p>
</asp:Content>

Best Solution

What result are you expecting from the AJAX call?

You could use the AjaxHelper object's helper methods instead of the HtmlHelper to render the link. For example, to get new content with an AJAX HttpPOST call and insert it into a <div> with the id set to ResultsGoHere you render the following link:

<%= Ajax.ActionLink("Edit", "ItemEdit", 
                         new {
                             itemId = item.RecordId, 
                             workstationId = myWorkStationId
                         },
                         new AjaxOptions {
                             HttpMethod="POST",
                             UpdateTargetId="ResultsGoHere",
                             InsertionMode = InsertionMode.Replace 
                         }) %>

In your AcionMethod, you can simply test on Request.IsAjaxRequest() to decide what to return:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ItemEdit(string itemId, string workstationId) {
    // edit the item and get it back

    if (Request.IsAjaxRequest()) {
        return PartialView("SingleItem", item);
    }
    return RedirectToAction("ItemEdit", new { itemId = item.RecordId, workstationId = workstationId });
}

// fallback for get requests
public ActionResult ItemEdit(string itemId, string workstationId)
{
    // do stuff and return view
}