根据ViewModel条目呈现复选框动态列表的最佳做法

问题描述

因此,由于我对MVC的经验不足,因此我目前正面临一个真正无法解决的问题。我正在为我们的Web应用程序实现权限模块。为此,我有一个称为“ SourceAccessviewmodel”的viewmodel,它看起来像这样。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Weytec.Wdp.Config.Grpc;
    using Weytec.Wdp.Data.Contracts;
    
    namespace Weytec.Wdp.Config.Web
    {
        public class SourceAccessviewmodel
        {

        public Guid? deviceid { get; set; }
        public Device Device { get; set; }
        public Guid ProfileId { get; set; }
        public bool? HasAccess { get; set; }
        public int SortOrder { get; set; }
        public string displayName { get; set; }
        public string DeviceName { get; set; }
        public bool? MouSEOnly { get; set; }
        public bool IsNew { get; set; } = false;
        public SourceAccessLevelPEnum AccessRight { get; set; }

        public List<EndpointAccessviewmodel> EndpointAccessRights { get; set; }

        public SourceAccessviewmodel()
        {

        }

        public SourceAccessviewmodel(InheritedSourceAccessRight entity)
        {
            deviceid = entity.deviceid;
            Device = entity.Device;
            DeviceName = entity.Device.Name;
            displayName = entity.displayName.Value;
            ProfileId = entity.ProfileId;
            MouSEOnly = entity.MouSEOnly.Value;
            EndpointAccessRights = entity.EndpointAccessRights.Values.Select(x => new EndpointAccessviewmodel(x)).ToList();
            AccessRight = entity.AccessRight.Value;
        }


        public SourceAccessviewmodel(SourceAccessRight entity)
        {
            deviceid = entity.deviceid;
            Device = entity.Device;
            ProfileId = entity.ProfileId;
            displayName = entity.displayName;
            DeviceName = entity.Device?.Name;
            MouSEOnly = entity.MouSEOnly;
            EndpointAccessRights = entity.EndpointAccessRights.Select(x => new EndpointAccessviewmodel(x)).ToList();
            AccessRight = entity.AccessRight;
        }
    }
}

In this viewmodel there is a List of viewmodels which are related to the endpoint access rights of the device.

It looks like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Weytec.Wdp.Config.Grpc;
    using Weytec.Wdp.Data.Contracts;
    
    namespace Weytec.Wdp.Config.Web
    {
        public class EndpointAccessviewmodel
        {
            public string EndpointName { get; set; }
            public Guid EndpointId { get; set; }
            public bool? HasAccess { get; set; }
    
            public EndpointAccessviewmodel()
            {
    
            }
    
            public EndpointAccessviewmodel(InheritedSourceAccessRight.InheritedEndpointAccessRight entity)
            {
            EndpointName = entity.Endpoint.Name;
            EndpointId = entity.EndpointId;
            HasAccess = entity.HasAccess.Value;
        }

        public EndpointAccessviewmodel(EndpointAccessRight entity)
        {
            EndpointName = entity.Endpoint.Name;
            EndpointId = entity.EndpointId;
            HasAccess = entity.HasAccess.Value;
        }
    }
}

我们可以看到其中有一个EndpointAccessRightsviewmodels列表,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Weytec.Wdp.Config.Grpc;
using Weytec.Wdp.Data.Contracts;

namespace Weytec.Wdp.Config.Web
{
    public class EndpointAccessviewmodel
    {
        public string EndpointName { get; set; }
        public Guid EndpointId { get; set; }
        public bool? HasAccess { get; set; }

        public EndpointAccessviewmodel()
        {

        }

        public EndpointAccessviewmodel(InheritedSourceAccessRight.InheritedEndpointAccessRight entity)
        {
            EndpointName = entity.Endpoint.Name;
            EndpointId = entity.EndpointId;
            HasAccess = entity.HasAccess.Value;
        }

        public EndpointAccessviewmodel(EndpointAccessRight entity)
        {
            EndpointName = entity.Endpoint.Name;
            EndpointId = entity.EndpointId;
            HasAccess = entity.HasAccess.Value;
        }
    }
}

现在是我的问题。在视图中,我像这样针对DeviceAccessRights渲染编辑模板:

@using (Html.BeginForm("EditaccessRights","User",new { deviceid = Model.deviceid,profileId = profileId },FormMethod.Post,true,null))
{
    @Html.HiddenFor(x => x.deviceid)
    @Html.HiddenFor(x => x.IsNew)
    <div>
        <div class="marginTop30px rowOfEntry">
            <div>Description:</div>
            <div>@Html.TextBoxFor(x => x.displayName,new { @class = "form-control",@id = "textBox",required = "required" })</div>
        </div>
        <div class="rowOfEntry">
            <div>Access right:</div>
            <div>@Html.DropDownListFor(x => x.AccessRight,Html.GetEnumSelectList(typeof(Weytec.Wdp.Config.Grpc.sourceAccessLevelPEnum)),new { @class = "form-control" })</div>
        </div>
        <div class="rowOfEntry">
            <div>Mouse Only:</div>
            @Html.EditorFor(model => model.MouSEOnly,new { htmlAttributes = new { @class = "form-control" } })
        </div>
    </div>

    <div class="marginTop20px">
        <input type="submit" onclick="fadeIn()" class="btn btn-success saveButtonPopup" value="Save" />
        <asp:Label id="savedForm" style="color: #0FB335" runat="server">Source access right saved</asp:Label>
    </div>

}

之后,我想为Endpoint访问呈现相同的内容,但是线索是它并不总是被填充。如果为端点设置了访问权限,则仅将其填充在Sourceaccessright viewmodel中。但是我还是想为这种情况渲染复选框,只是不选中。因此,目前,我只是使用复选框渲染相应设备的端点,但与SourceAccessRightviewmodel无关。

    @foreach (var endpoint in Model.Device.Endpoints)
    {

<div class="marginTop25px">
    <h5>Endpoint access right: @endpoint.Name</h5>

    @Html.EditorFor(x => x.EndpointAccessRights[i].HasAccess,new { htmlAttributes = new { @class = "form-control",@id = endpoint.Id } })
</div>
    }

也许一个选择是通过JSON解析视图模型,以便使用ajax请求,但这听起来并不是最好的解决方案。 我现在真的不知道该如何解决..有人可以帮我这个忙吗?

解决方法

我也遇到这种问题,并以此方式解决了。

您将获得所有EndpointAccessRight(不同类型),并将其与1 InheritedSourceAccessRight的EndpointAccessRight集合进行比较。如果类型不在集合中,则将其添加到集合中并将其设置为false或null。现在,您拥有一个完整的EndpointAccessRight集合,其中包含所有类型,并且视图将是统一的。

示例(可能并非100%正确)

foreach (var endpointAccessRight in allEndpointAccessRights)
        {
            if (!inheritedSourceAccessRight.EndPointAccessRights.Any(item => item.EndpointId == endpointAccessRight.EndpointId ))
            {
                endpointAccessRight.HasAccess = false; // or null
                inheritedSourceAccessRight.EndPointAccessRights.Add(endpointAccessRight);
            }
        }