Create a generic repository DropDown with SelectListItem in MVC

前端 未结 1 690
渐次进展
渐次进展 2021-01-28 11:26

Having returned to this problem after a few months I\'ve added my current best answer below.

In the original question I was still looking for a simple way to achieve a g

相关标签:
1条回答
  • 2021-01-28 12:25

    There is a way to create a generic DropDown which I've mangled together from a few pointers on StackOverflow and this article on CodeProject. Comments on whether this follows best practice would be appreciated.

    I use both an AddList and an EditList to allow for a selected item on the EditList and some jQuery based on html class attributes. The generic EditList is created as follows:

    Models

    I have a viewmodel for any DropDown that fits with the generic pattern and then a ViewModel for the entity I'm returning. Annotations are held in a validation file.

    DropDown ViewModel

    public class DropDownViewModel
    {
        public IEnumerable<SelectListItem> Items { get; set; }
    }
    

    Entity ViewModel

    public partial class OrganisationEditViewModel
    {
        public int entityID { get; set; }
        public string entityName { get; set; }
        public DropDownViewModel entityTypeID { get; set; }
        public string notes { get; set; }
    }
    

    Validation

    [MetadataTypeAttribute(typeof(OrganisationEditViewModelMetaData))]
    public partial class OrganisationEditViewModel
    {
    
    }
    
    public class OrganisationEditViewModelMetaData
    {
        [Key]
        [ScaffoldColumn(false)]
        [HiddenInput(DisplayValue = false)]
        public int entityID { get; set; }
    
        [Required]
        [Display(Name = "Organisation")]
        public string entityName { get; set; }
    
        [Required]
        [Display(Name = "Entity Type")]
        [UIHint("_dropDownEdit")]
        public DropDownViewModel entityTypeID { get; set; }
    
        [Display(Name = "Notes")]
        public string notes { get; set; }
    
    }
    

    Editor Template

    The UIHint annotation on the ViewModel points to an Editor Template. I'm using chosen.js on my lookups, hence the html attributes.

    @model WhatWorks.ViewModels.DropDownViewModel
    
    @Html.DropDownList("", Model.Items, new { @class = "chosen chosenLookup" })
    

    Controller

    The controller queries the current entity to get the selected string for the EditList. The DropDown is called from the GetEditList<O> function in the repository. The ViewModel is then mapped via Automapper (GetUpdate(id)).

    public ActionResult Edit(int id = 0)
    {
        var query = _repo.GetByID(id);
        string selected = query.tEntityType.entityTypeID.ToString();
    
        DropDownViewModel entityType = new DropDownViewModel
        {
            Items = _repo.GetEditList<tEntityType>("entityType", "entityTypeID", selected)
        };
    
        OrganisationEditViewModel a = GetUpdate(id);
        a.entityTypeID = entityType;
    
        if (a == null)
        {
            return HttpNotFound();
        }
        return View(a);
    }
    

    Repository

    The generic DropDown repository method gets an IEnumerable set of data from the calling type <O> (tEntityType in this case). The return method converts everything into strings and checks for the selected item.

    //generic Edit dropdown
        public IEnumerable<SelectListItem> GetEditList<O>(string text, string value, string selected) 
                                                            where O : class
        {
            IEnumerable<O> result = context.Set<O>();
            var query = from e in result
                        select new
                        {
                            Value = e.GetType().GetProperty(value).GetValue(e, null),
                            Text = e.GetType().GetProperty(text).GetValue(e, null)
                        };
    
            return query.AsEnumerable()
                .Select(s => new SelectListItem
                {
                    Value = s.Value.ToString(),
                    Text = s.Text.ToString(),
                    Selected = (selected == s.Value.ToString() ? true : false)
                });
        }
    

    View

    Finally, the view renders the DropDown via a standard Html.Editor which picks up the Editor Template from the UIHint annotation on the validation file.

    0 讨论(0)
提交回复
热议问题