简体   繁体   中英

ASP.NET MVC 5 DropDownList from another model

I'm just getting started with MVC. I'm building a project in asp.net mcv 5 using entity framework. I have researched many threads but I didn't find anything that would help solve my problem. I have two models:
Resource:

public class Resource
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public string Name { get; set; }

        public string Comments { get; set; }

        [Required]
        public ResourceType Type { get; set; }

        public bool IsActive { get; set; }
    }

ResourceType:

public class ResourceType
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public string Name { get; set; }
    }

And the problem is: In View > Resource > Create I want to add DropDownList for object ResourceType Type with values from class ResourceType string Name
Create.cshtml :

@model NetAudit.Models.Resource

@{
    ViewBag.Title = "Create Resource";
}

<h2>Create</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Resource</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Comments, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Comments, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Comments, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Type, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                HERE
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.IsActive, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                <div class="checkbox">
                    @Html.EditorFor(model => model.IsActive)
                    @Html.ValidationMessageFor(model => model.IsActive, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Dodaj" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to list", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

RecourceType controller:

using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using NetAudit.Models;

namespace NetAudit.Controllers
{
    public class ResourceTypesController : BaseController
    {
        private readonly ApplicationDbContext _db = new ApplicationDbContext();

        [Authorize]
        public ActionResult Index()
        {
            return View(_db.ResourceTypes.ToList());
        }
        [Authorize]
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            return View(resourceType);
        }
        [Authorize]
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]

        public ActionResult Create(ResourceType resourceType)
        {
            if (ModelState.IsValid)
            {
                _db.ResourceTypes.Add(resourceType);
                _db.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(resourceType);
        }
        [Authorize]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            return View(resourceType);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]

        public ActionResult Edit(ResourceType resourceType)
        {
            if (ModelState.IsValid)
            {
                _db.Entry(resourceType).State = EntityState.Modified;
                _db.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(resourceType);
        }
        [Authorize]
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            return View(resourceType);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]

        public ActionResult DeleteConfirmed(int id)
        {
            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            _db.ResourceTypes.Remove(resourceType);
            _db.SaveChanges();

            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _db.Dispose();
            }

            base.Dispose(disposing);
        }
    }
}

Resource controller:

using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using NetAudit.Models;

namespace NetAudit.Controllers
{
    public class ResourceTypesController : BaseController
    {
        private readonly ApplicationDbContext _db = new ApplicationDbContext();

        [Authorize]
        public ActionResult Index()
        {
            return View(_db.ResourceTypes.ToList());
        }
        [Authorize]
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            return View(resourceType);
        }
        [Authorize]
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]

        public ActionResult Create(ResourceType resourceType)
        {
            if (ModelState.IsValid)
            {
                _db.ResourceTypes.Add(resourceType);
                _db.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(resourceType);
        }
        [Authorize]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            return View(resourceType);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]

        public ActionResult Edit(ResourceType resourceType)
        {
            if (ModelState.IsValid)
            {
                _db.Entry(resourceType).State = EntityState.Modified;
                _db.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(resourceType);
        }
        [Authorize]
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            return View(resourceType);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]

        public ActionResult DeleteConfirmed(int id)
        {
            var resourceType = _db.ResourceTypes.Find(id);

            if (resourceType == null)
            {
                return HttpNotFound();
            }

            _db.ResourceTypes.Remove(resourceType);
            _db.SaveChanges();

            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _db.Dispose();
            }

            base.Dispose(disposing);
        }
    }
}

I spent a lot of time looking for a solution to this problem. I would appreciate your feedback on this.

First of you have a mistake to put Resource Controller here (both of Resource and ResourceType are ResourceType). fix it first.

Put in the Here section this code to render a select element from ViewBag.Types :

@Html.DropDownListFor(m => m.Type.Id, (SelectList)ViewBag.Types, new
                           {
                               @class = "form-control"
                           });

Before it you must fill ViewBag.Types in the action, Change the first Create action of ResourceController to this:

        [Authorize]
        public ActionResult Create()
        {
            ViewBag.Types = new SelectList(_db.ResourceTypes.ToList(), "Id", "Name", "0");
            return View();
        }

It will be worked.

I think the best way to get what you want is to create a ViewModel, this allows you create a view with various classes.

Under your solution create a new folder named ViewModels. Create a new class and name it CreateResourceViewModel.

    public class CreateResourceViewModel
{

   public Resource Resource {get;set;}
   public SelectList ResourceType {get;set;} //this will create the list of resourcetypes
   public int IdResourceType {get;set;} //this will be used to select the id of resourceType you are selecting.

public CreateResourceViewModel (Resource resource,List<ResourceType>resourceType) //create a constructor 
{
 this.Resource = resource;
//here you will set the list as a new selectList, stating where the list will come from. the Id de valuevaluefield, and the name is the valuetextfield
this.ResourceType= new SelectList(resourceType,"Id","Name");
}

public CreateResourceViewModel(){} //you need this second constructor

 }

Now you need a Create ActionResult that accepts a ViewModel in your resource Controller

  // GET: Locals/Create
    public ActionResult Create()
    {
        Resource resource = new Resource();
        List<ResourceType> resourceType;

        using (yourcontext db = new yourcontext())
        {
            resourceType = db.ResourceType.ToList(); //fill your list with the resourceTypes that are in your database

        }

        CreateResourceViewModel vm = new CreateResourceViewModel(resource,resourceType); //create a new viewmodel and give it the parameters necesary that we created


        return View(vm);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(CreateResourceViewModel vm)
    {
        using (yourcontext db = new yourcontext())
        {
            if (ModelState.IsValid)
            {
                try {
                    vm.Resource.Type = db.ResourceTpe.Find(vm.IdResourceType); //using the ID selected in the view find it in the database

                    db.Resources.Add(vm.Resource);
                    db.SaveChanges();
                    return RedirectToAction("Index");

                }
                catch (Exception e)
                {
                    e.Message();
                }
            }

            return View(vm);
        }
    }

Now onto the view for the ViewModel

    @model  yourSolution.ViewModels.CreateResourceViewModel

    @{
        ViewBag.Title = "Create";

    }


    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">
            <h4>Resource</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Comments, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Comments, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Comments, "", new { @class = "text-danger" })
                </div>
            </div>

         <div class="form-group">
                @Html.LabelFor(model => model.ResourceType, htmlAttributes: new { @class = "control-label col-md-2" })

//this is what you need to create a dropdownlist with all the resourceTypes

                <div class="col-md-10">
                    @Html.DropDownListFor(model => model.IdResourceType, Model.ResourceType,"--Select--" )
                </div>
            </div>



            <div class="form-group">
                @Html.LabelFor(model => model.IsActive, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    <div class="checkbox">
                        @Html.EditorFor(model => model.IsActive)
                        @Html.ValidationMessageFor(model => model.IsActive, "", new { @class = "text-danger" })
                    </div>
                </div>
            </div>

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Dodaj" class="btn btn-default" />
                </div>
            </div>
        </div>
    }

    <div>
        @Html.ActionLink("Back to list", "Index")
    </div>

    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }

Hope this helps!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM