views:

327

answers:

2

I have implemented the Ajax Autocomplete feature in my application using a web service file that querys my database and it works great. One problem I am having is allowing the user to see the item's name, as that's what they are typing in the textbox, but when they select it, it saves the item's ID number instead of the actual name. I want it to behave much like a dropdown list, where I can specify what is seen and entered vs. what is actually saved in the database (in this case, the product ID instead of it's name.)

I have this text box in my view, along with the script:

<script type="text/javascript">
    Sys.Application.add_init(function() {
        $create(

        AjaxControlToolkit.AutoCompleteBehavior, {
            serviceMethod: 'ProductSearch',
            servicePath: '/ProductService.asmx',
            minimumPrefixLength: 1,
            completionSetCount: 10
        },
        null,
        null,
        $get('ProductID'))
    });
    </script>
<p>
    <label for="ProductID">Product:</label>
    <%= Html.TextBox("ProductID", Model.Products)%>
    <%= Html.ValidationMessage("ProductID", "*")%>
</p>

Here's what is in my asmx file:

public class ProductService : System.Web.Services.WebService
{
    [WebMethod]
    public string[] ProductSearch(string prefixText, int count)
    {
        MyDataContext db = new MyDataContext();

        string[] products = (from product in db.Products
                             where product.ProductName.StartsWith(prefixText)
                             select product.ProductName).Take(count).ToArray();
        return products;
    }
}

Can anyone help me figure this out? I'm using this so they can just start typing instead of having a dropdown list that's a mile long...

+1  A: 

Hi,

Although this doesn't answer your question directly have you thought about using the Jquery autocomplete control?

From my experience it seems more flexible and you could link it up with your existing service and have more control over the data that is returned as well. Here the link if it helps.

Simon G
I also recommend using the jquery autocomplete plugin. Here is a very nice post on how to integrate it with asp.net mvc http://www.codevoyeur.com/Articles/10/ASP.NET-MVC-HtmlHelper-Extensions-for-jQuery-AutoComplete.aspx. Basically, for what you want, you have to make that when the user selects an option, the value (id) is placed in a hidden input.
uvita
thanks for the recommendation - I'll give it a whirl. Seems everyone says the same thing about jQuery vs Ajax
Ben
+1  A: 

the autocomplete control will post a json object to "servicePath/serviceMethod" so first, set the servicePath to your controller and the serviceMethod option to your action name.

then define this class:

public class AutoCompleteRequest
{
    public string PrefixText { get; set; }
    public int Count { get; set; }
} 

because thats the json object the autocomplete control posts to your controller.

then define a JsonModelBinder:

public class JsonBinderAttribute : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new JsonModelBinder();
    }

    public class JsonModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            try
            {
                var inputStream = controllerContext.HttpContext.Request.InputStream;
                using (var sr = new StreamReader(inputStream))
                {
                    var json = sr.ReadToEnd();
                    return JsonConvert.DeserializeObject(json, bindingContext.ModelType);
                }
            }
            catch
            {
                return null;
            }
        }
    }
}

this one is using Json.Net as deserializer.

then define your action like this:

    public virtual JsonResult SearchA([JsonBinder]AutoCompleteRequest post)
    {
        var data = repository.Query<A>()
            .Where(s => s.Name.StartsWith(post.PrefixText))
            .Take(post.Count)
            .Select(s => s.Name)
            .ToArray();
        return Json(data);
    }

note how i use the JsonBinderAttribute on the AutoCompleteRequest parameter and how a Json array of strings is returned.

Edit

i did a follow up blog post here: http://devcarl.posterous.com/how-to-use-ajax-library-4-autocomplete-with-a

Carl Hörberg