Home Binding async method into DropDownList ASP.NET MVC 5
Reply: 1

Binding async method into DropDownList ASP.NET MVC 5

Xardas
1#
Xardas Published in 2017-12-06 12:57:51Z

MachineDto:

[Required(ErrorMessage = "This field is required")]
[Display(Name = "Hardware Type")]
public string HardwareType { get; set; }
public IEnumerable<SelectListItem> ListOfHardwares { get; set; }

IHardwareRepository:

public interface IHardwareRepository
{
Task<Entities.Hardware>> GetAllHardwareAsync();
}

HardwareRepository:

public async Task<List<Entities.Hardware>> GetAllHardwareAsync()
        {
            var getAllHardware = await _appContext.Hardwares.ToListAsync();

            return getAllHardware;
        }

View:

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

EDIT:

Controller:

public class HardwareController : Controller
    {
private readonly IUnitOfWork _unitOfWork;

        public HardwareController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

public async Task<ActionResult> DisplayAll()
        {
            var displayAll = await _unitOfWork.HardwareRepository.GetAllHardwareAsync();

            return View(displayAll);
        }
}

EDIT2: Controller:

> public async Task<ActionResult> Add()
>         {
>             var model = new ImageDto();
>             var hardwares = await _unitOfWork.HardwareRepository.GetAllHardwareAsync();
> 
>             model.ListOfHardwares = hardwares.Select(h => new SelectListItem
>             {
>                 Text = h.Name,
>                 Value = h.Description
>             });
> 
>             return View();
}

View:

@model MachineDto

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

The problem is that now I want to pass GetAllHardwareAsync to ListOfHardwares and display it via DropDownList. I don't really want to do it by ViewBag. Any ideas? Thanks in advance!

David
2#
David Reply to 2017-12-06 14:01:19Z

Somewhere you simply need to set the value on the model using an instance of the repository. Where you do this depends on where you have (or can get) an instance of the repository and where you want to set the value on the model.

For example, in the majority of cases, the repository would be on the controller and the controller would build the model to send to the view. Which might look something like this...

private IHardwareRepository _repository;

public SomeController(IHardwareRepository repository)
{
    // I'm *assuming* you get the repository from dependency injection
    _repository = repository;
}

public async Task<ActionResult> SomeAction()
{
    var model = new MachineDto();
    model.ListOfHardwares = await _repository.GetAllHardwaresAsync();
    return View(model);
}

If you're not using dependency injection, perhaps you'd just instantiate your repository directly? Something like this:

public async Task<ActionResult> SomeAction()
{
    var repository = new HardwareRepository();
    var model = new MachineDto();
    model.ListOfHardwares = await repository.GetAllHardwaresAsync();
    return View(model);
}

Though that would defeat much of the purpose of the interface. It's really up to you how you manage your dependencies. The point is that you simply need to populate your model before sending it to the view. Then the elements on the view can bind to it.

Edit: Given your edit to the question, it looks like the repository is on a unit of work which is already injected into the controller. In that case it might look like this:

public async Task<ActionResult> DisplayAll()
{
    var model = new MachineDto();
    model.ListOfHardwares = await _unitOfWork.HardwareRepository.GetAllHardwareAsync();

    return View(model);
}

The view itself would of course also need the model declaration at the top, if you don't already have that (so it knows the model type):

@model MachineDto

Edit: On further inspection, it looks like your model wants an IEnumerable<SelectListItem> instead of just the actual data itself. I generally recommend doing that sort of projection in the view instead of the model, but not strongly enough to really discourage this practice entirely. Especially if this "model" is purely a view model for just this view.

In this case all you need is a simple projection. Once you have your list of results, you can project it to the list of the type you need. Something like this:

public async Task<ActionResult> DisplayAll()
{
    var model = new MachineDto();
    var hardwares = await _unitOfWork.HardwareRepository.GetAllHardwareAsync();
    model.ListOfHardwares = hardwares.Select(h => new SelectListItem
    {
        Text = h.SomeTextProperty,
        Value = h.SomeIdentifierProperty
    });
    return View(model);
}

What you use for SomeTextProperty and SomeIdentifierProperty depends on what properties exist on Hardware and how you want to use those to build your select list.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.305888 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO