【问题标题】:Access common view for different models with same columns访问具有相同列的不同模型的通用视图
【发布时间】:2020-05-07 08:58:00
【问题描述】:

我正在开发一个 MVC 应用程序,它具有 D1、D2、D3 和 D4 阶段,我们将从应用程序中加载/编辑每个阶段。

现在,我已经为每个阶段模型创建了单独的模型和单独的视图,如下所示并使用它。但为了代码重用,我想对所有阶段(D1、D2、D3 和 D4)使用通用视图,因为所有阶段都包含相同的列。

我有一个想法,通过为所有四个阶段创建单个视图模型并加以利用来实现,但我们需要分别编辑和保存这些值。所以我对这一点感到震惊。有没有办法通过加载和保存每个阶段的数据来为所有四个模型使用一个通用视图。

实体

public partial class D1Stage : EntityBase
{
    [DisplayName("Status Indicator")]
    public byte StatusIndicatorId { get; set; }

    [DisplayName("Status Info")]
    public string StatusInfo { get; set; }

    [DisplayName("Completed %")]
    [SCIRange(0, 100)]
    public decimal StageCompletion { get; set; }

    [DisplayName("Is Step Mandatory")]
    public bool IsMandatory { get; set; }
}

正如我提到的,D2StageD3StageD4Stage 具有完全相同的属性,例如 D2Stage

public partial class D2Stage : EntityBase
{
    ... exact same properties as D1Stage 
}

观看次数

@model Brain.DAL.Entities.D1Stage
@{
    IEnumerable<SelectListItem> StatusIndicators = ViewBag.StatusIndicators;
}

@using (Html.BeginForm("", "", FormMethod.Post, new { enctype = "multipart/form-data", @class = "form form-horizontal" }))
{
    <div class="form-body">
        @Html.AntiForgeryToken()
        @Html.HiddenFor(model => model.Id)
        @Html.HiddenFor(model => model.Report.Id)
        <div class="form-group">
            @Html.SCILabelFor(model => model.StatusIndicatorId, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                @Html.DropDownListFor(model => model.StatusIndicatorId, new SelectList(StatusIndicators, "Value", "Text"), "None", new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.StatusIndicatorId, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.SCILabelFor(model => model.StatusInfo, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                @Html.TextAreaFor(model => model.StatusInfo, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.StatusInfo, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.SCILabelFor(model => model.StageCompletion, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                @Html.SCINumericTextBoxFor(model => model.StageCompletion, new { @class = "form-control sliderrangemintext", @style = "width:100px" })

                <div class="sliderrangemin" id="slider-range-min" style="margin-top:50px"></div>
            </div>            
        </div>
        <div class="form-group">
            @Html.SCILabelFor(model => model.IsMandatory, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                <div class="input-group" style="width:100%">
                    @Html.DropDownListFor(model => model.IsMandatory, new List<SelectListItem>() { new SelectListItem { Text = "No", Value = "false" }, new SelectListItem { Text = "Yes", Value = "true", Selected = true } }, htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.IsMandatory, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>
    </div>
}

正如我上面提到的,所有其他视图都有相同的内容,只是对应的模型不同。例如D2Stage

@model Brain.DAL.Entities.D2Stage
... The difference is just in model. 
... Rest of the content is exactly the same as D1Stage view

【问题讨论】:

  • 所有模型都有相似的属性?创建单个模型或将属性移动到基类并创建 4 个从基模型派生的模型。然后还创建一个以基本模型为模型的单一视图。
  • 不清楚为什么不能在所有阶段都使用相同的StageViewModel 和相同的View?也许您只需要在StageViewModel 中添加一个StageNumber 来指示当前阶段?

标签: c# .net asp.net-mvc razor view


【解决方案1】:

所有模型都有相似的属性?假设您无法创建单个模型。然后将属性移动到基类并创建从基模型派生的其他模型。然后还创建一个以基本模型为模型的单一视图。

模型

public class MyBaseModel
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

public class ModelA: MyBaseModel{}
public class ModelB: MyBaseModel{}

查看

MyBaseModel 创建一个视图,并将视图放在Shared 文件夹中,并将其命名为MySharedView

@model MyNamespace.MyBaseModel

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

    <div class="form-horizontal">
        <h4>Title which you can decide based on model type or get from ViewBag</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Property1, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Property1, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Property1, "", new { @class = "text-danger" })
            </div>
        </div>

        ... Rest of properties ...

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

控制器

然后在控制器中,当你想要返回视图时,指定共享视图名称。例如模型A 和模型B 相同:

[HttpGet]
public ActionResult A()
{
    var model = new ModelA() { Property1 = "A", Property2 = "A" };
    return View("MySharedView", model);
}
[HttpPost]
public ActionResult A(ModelA model)
{
    // SaveA(model)
    // Redirect to index
}

【讨论】:

  • 感谢您的即时回复。我会试试这个。单击保存按钮时如何保存,它应该保存在单独的表格中?
  • 如果您需要不同的处理,您有不同的操作。每个动作都会收到它应该处理的模型。
  • 我可以扩展答案以包含更多选项,但老实说,重点是为所有模型提供一个基类,并为基本模型提供一个视图,这并不容易更多倡议。
  • 您还可以重新设计模型,使用单个模型,具有所有提到的属性 + 另一个属性 public int Stage { get ;set;} 并将所有数据保存在一个表中。但我认为这是一个显而易见的解决方案,您不想更改模型和后面的所有表格。
  • @VigneshKumarA 我相信这篇文章回答了这个问题的主要问题。如果您对此有任何疑问或觉得它有用,请告诉我。
【解决方案2】:

看来您应该使用模式 ModelFactory。 使用属性和方法(仅声明)创建一个接口 IStage。然后所有的 D*Stage 类都实现了 IStage。因此视图具有模型 IStage。 这样每个类都可以在每个方法中做不同的事情。

    interface IStage{

        byte StatusIndicatorId { get; set; }

        string StatusInfo { get; set; }

        decimal StageCompletion { get; set; }

        bool IsMandatory { get; set; }

    }

     public partial class D1Stage : EntityBase, IStage
     {
        [DisplayName("Status Indicator")]
        public byte StatusIndicatorId { get; set; }

    [DisplayName("Status Info")]
    public string StatusInfo { get; set; }

    [DisplayName("Completed %")]
    [SCIRange(0, 100)]
    public decimal StageCompletion { get; set; }

    [DisplayName("Is Step Mandatory")]
    public bool IsMandatory { get; set; }

    }

@查看

    @model IStage
    @{
    IEnumerable<SelectListItem> StatusIndicators = ViewBag.StatusIndicators;
    }

   @using (Html.BeginForm("", "", FormMethod.Post, new { enctype = "multipart/form-data", 
   @class = "form form-horizontal" }))
    {
       <div class="form-body">
           @Html.AntiForgeryToken()
           @Html.HiddenFor(model => model.Id)
           @Html.HiddenFor(model => model.Report.Id)
           <div class="form-group">
               @Html.SCILabelFor(model => model.StatusIndicatorId, new { @class = "col-md-1 control-label" })
                  <div class="input-group col-md-4">
                   @Html.DropDownListFor(model => model.StatusIndicatorId, new SelectList(StatusIndicators, "Value", "Text"), "None", new { @class = "form-control" })
                   @Html.ValidationMessageFor(model => model.StatusIndicatorId, "", new { @class = "text-danger" })
               </div>
           </div>
           <div class="form-group">
               @Html.SCILabelFor(model => model.StatusInfo, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                @Html.TextAreaFor(model => model.StatusInfo, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.StatusInfo, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.SCILabelFor(model => model.StageCompletion, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                @Html.SCINumericTextBoxFor(model => model.StageCompletion, new { @class = "form-control sliderrangemintext", @style = "width:100px" })

                <div class="sliderrangemin" id="slider-range-min" style="margin-top:50px"></div>
            </div>            
        </div>
        <div class="form-group">
            @Html.SCILabelFor(model => model.IsMandatory, new { @class = "col-md-1 control-label" })
            <div class="input-group col-md-4">
                <div class="input-group" style="width:100%">
                    @Html.DropDownListFor(model => model.IsMandatory, new List<SelectListItem>() { new SelectListItem { Text = "No", Value = "false" }, new SelectListItem { Text = "Yes", Value = "true", Selected = true } }, htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.IsMandatory, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>
    </div>
    }

这样就只有一个视图了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多