title: How do I make text box autocomplete result selection navigate directly to record details?
body: <p>I’m developing a CRUD project using ASP.NET MVC 4. There is a requirement to implement an autocomplete on search form text fields. I’ve been able to implement this using jQuery just fine using json. But this simply populates the text box with a search term when you select one of the autocomplete results. The functionality I need though is, when the user selects one of the autocomplete results (Which will display several fields of a record) the app goes directly to the details of that record instead of just putting the string value in the text box. How can this be done?</p>
  
  <p>Below is my implementation of the autocomplete that simply places string values in text boxes if anyone happens to be looking for that kind of solution. I made a reusable partial view that I can plug into different views:</p>
  
  <p><strong>Create javascript autocomplete with json in MVC</strong></p>
  
  <p>Parameterized script in partial, re-usable cshtml class:</p>
  
  <pre><code>@{
    var boxId = ViewData["BoxId"];
    var controller = ViewData["Controller"];
    var action = ViewData["Action"];
    var paramName = ViewData["ActionParamName"];
    var dataField = ViewData["DataFieldName"];
    var data = "item." + dataField;
  }
  
  &lt;script src="~/Scripts/jquery-1.4.1.min.js" type="text/javascript"&gt;&lt;/script&gt;
  &lt;script src="~/Scripts/jquery.autocomplete.min.js" type="text/javascript"&gt;&lt;/script&gt;
  
  &lt;script type="text/javascript"&gt;
    $(document).ready(function () {
      $("#@(boxId)").autocomplete({
          source: function (request, response) {
              $.ajax({
                  url: "/@(controller)/@(action)",
                  type: "POST",
                  dataType: "json",
                  data: { @paramName : request.term },
                  success: function (data) {
                      response($.map(data, function (item) {
                          return { label: @data , value: @data };
                      }))
  
                  }
              })
          },
          messages: {
              noResults: "", results: ""
          }
      });
   })
  &lt;/script&gt;
  </code></pre>
  
  <p><strong>NOTE</strong>:: The DataFieldName is the name of the accessor on the result object. In this case the APP_People_SEARCH_Result object has an accessor named FirstName </p>
  
  <p><strong>ALSO</strong>:: The ActionParamName must match the name of the argument in the action method in the controller class. In this case it’s firstName (i.e. string firstName)</p>
  
  <p>Script on your View where it will be used:</p>
  
  <pre><code>@Html.Partial("_AutoComplete",  new ViewDataDictionary { new KeyValuePair&lt;string, object("BoxId", "FirstNameTextBox"), new KeyValuePair&lt;string, object&gt;("Controller", "People"), new     KeyValuePair&lt;string, object&gt;("Action", "FirstNameAutoComplete"), new KeyValuePair&lt;string, object&gt;    ("ActionParamName", "firstName"), new KeyValuePair&lt;string, object&gt;("DataFieldName", "FirstName") })
  
  @using (Html.BeginForm("Select", "People", FormMethod.Post, new { @class = "myclass", id = "" }))
  {
    &lt;p&gt;First Name: @Html.TextBox("firstName", null, new { id = "FirstNameTextBox" })    &lt;/p&gt;
  
    &lt;p&gt;&lt;input type="submit" value="Search" /&gt;&lt;/p&gt;
  }
  </code></pre>
  
  <p>Code in PeopleController.cs:</p>
  
  <pre><code>public JsonResult FirstNameAutoComplete(string firstName)
      {
          List&lt;APP_People_SEARCH_Result&gt; results = RunSearch(firstName, false);
  
          return Json(results, JsonRequestBehavior.AllowGet);
      }
  </code></pre>
  
  <p>How it looks in source:</p>
  
  <pre><code>&lt;script src="/Scripts/jquery-1.4.1.min.js" type="text/javascript"&gt;&lt;/script&gt;
  &lt;script src="/Scripts/jquery.autocomplete.min.js" type="text/javascript"&gt;&lt;/script&gt;
  &lt;script type="text/javascript"&gt;
      $(document).ready(function () {
          $("#FirstNameTextBox").autocomplete({
              source: function (request, response) {
                  $.ajax({
                  url: "/People/FirstNameAutoComplete",
                  type: "POST",
                  dataType: "json",
                  data: { firstName : request.term },
                  success: function (data) {
                      response($.map(data, function (item) {
                          return { label: item.FirstName , value: item.FirstName };
                      }))
  
                  }
              })
          },
          messages: {
              noResults: "", results: ""
          }
      });
  })
  &lt;/script&gt; 
  
  
  &lt;form action="/People/Select" class="myclass" method="post"&gt;    
      &lt;p&gt;First Name: &lt;input id="FirstNameTextBox" name="firstName" type="text" value="" /&gt;    &lt;/p&gt;
      &lt;p&gt;&lt;input type="submit" value="Search" /&gt;&lt;/p&gt;
  &lt;/form&gt; 
  </code></pre>
  
  <p><strong>Thanks to Silkster for the assistance.</strong></p>
  
  <p>I was able to implement an almost reusable partial cshtml file:</p>
  
  <pre><code>@{
  var boxId = ViewData["BoxId"];
  var controller = ViewData["Controller"];
  var action = ViewData["Action"];
  var paramName = ViewData["ActionParamName"];
  var idFieldID = ViewData["IdFieldID"];
  var objectIdProperty = ViewData["ObjectId"];
  var objectId = "item." + objectIdProperty;
  //var recordResult = ViewData["RecordResult"];////doesnt work for label and value, have to hard-code it
  }
  
  &lt;script src="~/Scripts/jquery-1.4.1.min.js" type="text/javascript"&gt;&lt;/script&gt;
  &lt;script src="~/Scripts/jquery.autocomplete.min.js" type="text/javascript"&gt;&lt;/script&gt;
  
  &lt;script type="text/javascript"&gt;
  $(document).ready(function () {
      $("#@(boxId)").autocomplete({
          source: function (request, response) {
              $.ajax({
                  url: "/@(controller)/@(action)",
                  type: "POST",
                  dataType: "json",
                  data: { @paramName : request.term },
                  success: function (data) {
                      response($.map(data, function (item) {
                          return { 
                              label: item.FirstName + ' ' + item.LastName + ' ' + item.Department , 
                              value: item.FirstName + ' ' + item.LastName + ' ' + item.Department , 
                              recordKey : @objectId
  
                          };
                      }))
  
                  }
              })
          },
          messages: {
              noResults: "", results: ""
          },
          select: function (event, ui) {
              if (ui.item) {
                  var elem = document.getElementById("@(idFieldID)");
                  elem.value = ui.item.recordKey;
  
                  $("form").submit();
              }
          }
      });
   })
  &lt;/script&gt;
  </code></pre>
  
  <p>In my view I add a hidden text box to store the ID of an objedct. I can almost totally paramaterize the partial (as seen above) except when I try to pass in a string that contains quotes, they don't translate in the produced script.</p>
  
  <p>The View:</p>
  
  <pre><code>//Couldn't get the following to work
  @*@Html.Partial("_PeopleAutoComplete",  new ViewDataDictionary { new KeyValuePair&lt;string, object&gt;("BoxId", "FirstNameTextBox"), new KeyValuePair&lt;string, object&gt;("Controller", "People"), new KeyValuePair&lt;string, object&gt;("Action", "FirstNameAutoComplete"), new KeyValuePair&lt;string, object&gt;("ActionParamName", "firstName"), new KeyValuePair&lt;string, object&gt;("IdFieldID", "people_ID"), new KeyValuePair&lt;string, object&gt;("ObjectId", "People_ID")  , new KeyValuePair&lt;string, object&gt;("RecordResult", "item.FirstName + ' ' + item.LastName + ' ' + item.Department") })*@
  
  //So I had to just use this. Values ended up being hard-coded
  @Html.Partial("_PeopleAutoComplete",  new ViewDataDictionary { new KeyValuePair&lt;string, object&gt;("BoxId", "FirstNameTextBox"), new KeyValuePair&lt;string, object&gt;("Controller", "People"), new KeyValuePair&lt;string, object&gt;("Action", "FirstNameAutoComplete"), new KeyValuePair&lt;string, object&gt;("ActionParamName", "firstName"), new KeyValuePair&lt;string, object&gt;("IdFieldID", "people_ID"), new KeyValuePair&lt;string, object&gt;("ObjectId", "People_ID")})
  
  @Html.Partial("_PeopleAutoComplete",  new ViewDataDictionary { new KeyValuePair&lt;string, object&gt;("BoxId", "LastNameTextBox"), new KeyValuePair&lt;string, object&gt;("Controller", "People"), new KeyValuePair&lt;string, object&gt;("Action", "LastNameAutoComplete"), new KeyValuePair&lt;string, object&gt;("ActionParamName", "lastName"), new KeyValuePair&lt;string, object&gt;("IdFieldID", "people_ID"), new KeyValuePair&lt;string, object&gt;("ObjectId", "People_ID")})
  
  @using (Html.BeginForm("SearchResults", "People"))
  {
    &lt;p&gt;&lt;input type="submit" value="Search" /&gt;&lt;/p&gt;
  
    @Html.TextBox("people_ID", null, new {id = "people_ID", style = "display:none;" })
  
    &lt;p&gt;First Name: @Html.TextBox("firstName", null, new { id = "FirstNameTextBox" })&lt;/p&gt;
    &lt;p&gt;Last Name: @Html.TextBox("lastName", null, new { id = "LastNameTextBox" })&lt;/p&gt;
  }
  </code></pre>
  
  <p>In my controller I first do a check to see if People_ID is null. If it's not I redirect to the details screen using the ID selected:</p>
  
  <pre><code>if (people_ID != null)
          {
              return RedirectToAction("Details", "People", new RouteValueDictionary(new { id = (int)people_ID }));
          }
  </code></pre>