代码之家  ›  专栏  ›  技术社区  ›  Ben

在ASP.NET MVC项目中自动完成Ajax—如何显示对象的名称,但实际保存它的ID?

  •  0
  • Ben  · 技术社区  · 15 年前

    我已经在我的应用程序中实现了Ajax自动完成功能,它使用一个查询我的数据库的Web服务文件,并且工作得很好。我遇到的一个问题是允许用户看到项目的名称,就像他们在文本框中键入的那样,但是当他们选择它时,它会保存项目的ID号而不是实际的名称。我希望它的行为与下拉列表非常相似,在下拉列表中,我可以指定看到和输入的内容与实际保存在数据库中的内容(在本例中,是产品ID而不是其名称)。

    我的视图中有此文本框,以及脚本:

    <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>
    

    以下是我的asmx文件中的内容:

    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;
        }
    }
    

    有人能帮我解决这个问题吗?我用这个,这样他们就可以开始打字,而不是有一个一英里长的下拉列表…

    2 回复  |  直到 15 年前
        1
  •  1
  •   Carl Hörberg    15 年前

    autocomplete控件会将JSON对象发布到“servicePath/serviceMethod”中,因此首先设置 servicePath 到你的控制器和 serviceMethod 操作名称的选项。

    然后定义这个类:

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

    因为这是json对象,所以autocomplete控件将发布到控制器。

    然后定义一个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;
                }
            }
        }
    }
    

    这一个使用json.net作为反序列化程序。

    然后这样定义你的行为:

        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);
        }
    

    请注意,我如何在autocompleteRequest参数上使用jsonbinderattribute,以及如何返回字符串的json数组。

    编辑

    我在这里写了一篇后续博客: http://devcarl.posterous.com/how-to-use-ajax-library-4-autocomplete-with-a

        2
  •  1
  •   lancscoder    15 年前

    虽然这不能直接回答您的问题,您是否考虑过使用jquery自动完成控件?

    根据我的经验,它看起来更灵活,您可以将它与现有的服务连接起来,并对返回的数据有更多的控制。这里 link 如果有帮助的话。