Доступ к общему виду для разных моделей с одинаковыми столбцами - PullRequest
0 голосов
/ 21 января 2020

Я работаю над приложением MVC, которое имеет этапы D1, D2, D3 и D4, и мы будем загружать / редактировать каждый этап из приложения.

Прямо сейчас я создал отдельное модели и отдельные виды для каждой модели этапа, как показано ниже, и их использование. Но для повторного использования кода я хотел бы использовать общее представление для всех этапов (D1, D2, D3 и D4), поскольку все этапы содержат одинаковые столбцы.

У меня есть идея реализовать путем создания одного представления. модель для всех четырех этапов и использования, но нам нужно редактировать и сохранять значения отдельно. Так что я поражен этим моментом. Есть ли идея использовать общий вид для всех четырех моделей путем загрузки и сохранения данных для каждого этапа.

Entities

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

И, как я уже говорил, D2Stage, D3Stage и D4Stage имеют абсолютно одинаковые свойства, например для 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

Ответы [ 2 ]

1 голос
/ 31 января 2020

Кажется, вам следует использовать шаблон ModelFactory. Создайте интерфейс IStage со свойствами и методом (только объявления). Тогда весь класс D * Stage реализует IStage. Так что View имеет в качестве модели 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; }

    }

@ View

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

Таким образом, существует только одно представление.

1 голос
/ 27 января 2020

Все модели имеют схожие свойства? Предполагая, что вы не можете создать одну модель. Затем переместите свойства в базовый класс и создайте другие модели, основанные на базовой модели. Затем также создайте одно представление с базовой моделью в качестве модели.

Модели

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
}

...