【问题标题】:Binding async method into DropDownList ASP.NET MVC 5将异步方法绑定到 DropDownList ASP.NET MVC 5
【发布时间】:2018-05-20 08:51:26
【问题描述】:

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

硬件存储库

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

            return getAllHardware;
        }

查看:

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

编辑

控制器:

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: 控制器:

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

查看:

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

问题是现在我想将 GetAllHardwareAsync 传递给 ListOfHardwares 并通过 DropDownList 显示它。我真的不想通过 ViewBag 来做。有任何想法吗? 提前致谢!

【问题讨论】:

    标签: asp.net entity-framework asynchronous asp.net-mvc-5 async-await


    【解决方案1】:

    您只需要使用存储库的实例在模型上设置值。 在哪里您执行此操作取决于您拥有(或可以获得)存储库实例的位置以及您希望在模型上设置值的位置。

    例如,在大多数情况下,存储库将位于控制器上,而控制器将构建模型以发送到视图。这可能看起来像这样......

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

    如果您不使用依赖注入,也许您只是直接实例化您的存储库?像这样的:

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

    虽然这会破坏界面的大部分目的。如何管理依赖项完全取决于您。关键是您只需要在将模型发送到视图之前填充模型。然后视图上的元素可以绑定到它。

    编辑:鉴于您对问题的编辑,看起来存储库位于已注入控制器的工作单元上。在这种情况下,它可能看起来像这样:

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

    视图本身当然也需要顶部的模型声明,如果你还没有的话(所以它知道模型类型):

    @model MachineDto
    

    编辑:进一步检查,您的模型似乎需要IEnumerable&lt;SelectListItem&gt; 而不仅仅是实际数据本身。我通常建议在 view 而不是模型中进行这种投影,但强度不足以完全阻止这种做法。特别是如果这个“模型”纯粹是这个视图的视图模型。

    在这种情况下,您只需要一个简单的投影。获得结果列表后,您可以将其投影到所需类型的列表中。像这样的:

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

    您对SomeTextPropertySomeIdentifierProperty 的使用取决于Hardware 上存在的属性以及您希望如何使用这些属性来构建您的选择列表。

    【讨论】:

    • 如果我像你一样写,那么在:model.ListOfHardwares = _unitOfWork.HardwareRepository.GetAllHardwaresAsync() VS 说不能隐式转换类型 'System.Threading.Tasks.Task >' 到 'System.Collections.Generic.IEnumerable'。存在显式转换(您是否缺少演员表?)
    • @Xardas:你忘记了 await 关键字。使用await,结果是List&lt;Entities.Hardware&gt;。没有它,结果是Task&lt;List&lt;Entities.Hardware&gt;&gt;。正如错误所述,它们是不同的类型。
    • 确实,我忘记了等待,但仍然没有解决问题。
    • @Xardas:你能进一步描述这个问题吗?它以什么方式失败?
    • MachineDto 具有从 ListOfHardwares 获取的 HardWareType 字段。 ListOfHardwares 直接取自 DB,因为 Hardwares 可以单独放入 Db。所以这意味着我有单独的硬件和机器存储库。问题是我想将 HardwareRepository(顺便说一句包含在 UnitOfWork 中)的返回值传递给 Machine 中的 ListOfHardwares。起初我是这样通过 ViewBag 做到的:ViewBag.ListOfRpsw = new SelectList(_rpswRepository.GetAllRpsw(), "Name", "Description"); 并且它有效,但由于我添加了 async&await 和 UnitOfWork 它停止工作。
    猜你喜欢
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多