用新编辑的MVC索引(增强视图模型)

时间:2018-06-15 15:03:28

标签: asp.net-mvc controller ef-code-first

(编辑)的 我有一个产品(产品)表,它在名为ProductCatalog的视图中显示,用户可以在其中找到产品表中的所有产品。我正在使用标准(索引)视图。

我现在想要实现的是可以选择(单击)目录中的单个产品并显示产品的详细视图的场景(类似于CRUD中的标准编辑/详细信息方法)。 但是,在此详细信息视图(ProductDetails)中,我需要增强模型,因为用户将确定变量,例如应该过帐到新表(LineItems)的订单数量以及产品中的属性( ProductID,主要是为了最终创建订单。

我一直未能实现这一目标。不确定我是否需要使用mutliple视图模型或做一些我不了解的其他奇特的东西。

总而言之,问题是如何从Index转到Details和Details以将不同的viewmodel发布到某个DB。所有这一切都与EF。

型号:

da.attrs['long_name'] = 'new_long_name'

查看

    public class Products
{
    public int                                                      ID                                  { get; set; }
    public int                                                      CategoryID                          { get; set; }
    public string                                                   ProductName                         { get; set; }
    public string                                                   ProductDescription                  { get; set; }
    public string                                                   ProductPicturePath                  { get; set; }
    public string                                                   UnitCost                            { get; set; }
    public string                                                   UnitPrice                           { get; set; }
    public string                                                   LowestUnitPrice                     { get; set; }
    public string                                                   SubscriptionPrice                   { get; set; }
    public string                                                   UnitMargin                          { get; set; }
    public string                                                   UnitProfit                          { get; set; }
    public bool                                                     InCatalog                           { get; set; }
}


    public class ProductViewModel
{
    public int                                                      ProductID                           { get; set; }

    public string                                                   ProductName                         { get; set; }

    public string                                                   ProductDescription                  { get; set; }

    public string                                                   ProductPicturePath                  { get; set; }

    [RegularExpression(@"^\((\d{3}?)\)$", ErrorMessage              = "Du brauchst die Anzahl nicht ausschreiben - verwende Ziffern.")]
    [Display(Name                                                   = "Bestellmenge")]
    public string                                                   SubscriptionQuantity                { get; set; }

    [Display(Name                                                   = "Lieferrhytmus")]
    public string                                                   SubscriptionCadenceCategory         { get; set; }

    public string                                                   SubscriptionCadenceValue            { get; set; }

    [Display(Name                                                   = "Preis im Abonnement")]
    public string                                                   SubscriptionPrice                   { get; set; }

    public bool                                                     IsSingleOrder                       { get; set; }

    [RegularExpression(@"^\((\d{3}?)\)$", ErrorMessage              = "Du brauchst die Anzahl nicht ausschreiben - verwende Ziffern.")]
    [Display(Name                                                   = "Bestellmenge")]
    public string                                                   Quantity                            { get; set; }

    [Display(Name =                                                 "Preis pro Einheit")]
    public string                                                   UnitPrice                           { get; set; }

    public DateTime                                                 ActivityDateTime                    { get; set; }

    public string                                                   ActivityLatitude                    { get; set; }

    public string                                                   ActivityLongitude                   { get; set; }

    public string                                                   ActivityLocation                    { get; set; }


}

ProductDetails(查看)

@using freshNclean.Models
@model IEnumerable<freshNclean.Models.Products>
@{
    ViewBag.Title = "Sortiment";
}
<div id="productCatalogContainer" class="container">
    <div id="productCatalogHeaderSection" class="headerSection">
        <h1 id="productCatalogHeaderTitle" class="headerTitle">
            @ViewBag.Title
        </h1>
        <i id="productCatalogHeaderIcon" class="headerIcon fas fa-gem" aria-hidden="true"></i>
    </div>
<!-- table section -->
    <section id="productCatalogListPartialSection" class="table">
        <div id="productCatalogSeparatorSection" class="separatorSection">
            <hr id="productCatalogSeparator" class="separator" />
        </div>
        <div id="productCatalog" class="productTableSection row">
             @foreach (var item in Model)
            {
                if (item.InCatalog == true)
                {
                    <a id="productCatalogProductArea" class="tableArea col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-3 col-lg-offset-2 col-lg-3" href="@Url.Action("ProductDetails", "freshNclean", new { id = item.ID })">
                        @Html.HiddenFor(modelItem => item.ID, new { @class = "tableField col-xs-12 col-sm-12 col-md-12 col-lg-12" })
                        <img id="productCatalogProductImage" class="tableImage col-xs-12 col-sm-12 col-md-12 col-lg-12" src="@Url.Content(item.ProductPicturePath)" alt="Produktbild" />
                        <div id="productCatalogProductNameField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
                            @Html.DisplayFor(modelItem => item.ProductName)
                        </div>
                        <div id="productCatalogProductDescriptionField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
                            @Html.DisplayFor(modelItem => item.ProductDescription)
                        </div>

                        <div id="productCatalogLowestUnitPriceField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
                            ab @Html.DisplayFor(modelItem => item.LowestUnitPrice)
                        </div>
                    </a>
                }
            }
        </div>

        <div id="productCatalogListPartialMenuSeparatorSection" class="separatorSection">
            <hr id="productCatalogListPartialMenuSeparator" class="separator" />
        </div>
        @Html.ActionLink("zum Warenkorb", "ShowShoppingCart", "", htmlAttributes: new { @class = "formButton col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-3 col-md-6 col-lg-offset-3 col-lg-6" })
    </section>
</div>
<!-- link back to menu -->
<div id="productCatalogReturnToMenuSection" class="linkSection">
    @Html.ActionLink("zurück zum Menü", "Profile", "", htmlAttributes: new { @id = "productCatalogReturnToMenuButton", @class = "link" })
</div>
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
<!-- Google Places -->
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBYK8aBCsb1dFrzXqIgUq07ZwO3w3_fGCs&libraries=places&callback=initAutocomplete" async defer></script>
}

控制器

@model freshNclean.Models.Products
@{
    ViewBag.Title = "Sortiment";
}
<div id="productCatalogContainer" class="container">
<div id="productCatalogHeaderSection" class="headerSection">
    <h1 id="productCatalogHeaderTitle" class="headerTitle">
        @ViewBag.Title
    </h1>
    <i id="productCatalogHeaderIcon" class="headerIcon fas fa-gem" aria-hidden="true"></i>
</div>
<!-- form -->
<section id="productDetailsForm" class="form">
    @using (Html.BeginForm("ShowProduct", "freshNclean", FormMethod.Post, new { @id = "productDetailsFormContainer", @class = "form-horizontal", @role = "form" }))
    {
        @Html.AntiForgeryToken()
<!-- user activities (hidden) -->
        @Html.HiddenFor(m => m.ActivityLatitude, new { @id = "productDetailsActivityLatitudeField", @class = "userActivityField" })
        @Html.HiddenFor(m => m.ActivityLongitude, new { @id = "productDetailsActivityLongitudeField", @class = "userActivityField" })
        @Html.HiddenFor(m => m.ActivityLocation, new { @id = "productDetailsActivityLocationField", @class = "userActivityField" })
<!-- autopopulate user activity fields with location -->
        <script>
            $(document).ready(function defaultValue() {
                if (!navigator.geolocation) return;
                navigator.geolocation.getCurrentPosition(function (userCoordinates) {
                    geocoder = new google.maps.Geocoder();
                    userLatLng = new google.maps.LatLng(userCoordinates.coords.latitude, userCoordinates.coords.longitude);
                    document.getElementById('productDetailsActivityLatitudeField').value = userCoordinates.coords.latitude;
                    document.getElementById('productDetailsActivityLongitudeField').value = userCoordinates.coords.longitude;
                    geocoder.geocode({ 'latLng': userLatLng }, function (results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            var result = results[0];
                            locationPlaceholder = "";
                            for (var i = 0, len = result.address_components.length; i < len; i++) {
                                var addressComponent = result.address_components[i];
                                if (addressComponent.types.indexOf("locality") >= 0) locationPlaceholder = addressComponent.long_name;
                            }
                            if (locationPlaceholder != '') {
                                document.getElementById('productDetailsActivityLocationField').value = locationPlaceholder;
                            }
                        }
                    });
                });
            });
        </script>
<!-- form: product display -->
        <div id="productDetailsProductDisplaySeparatorSection" class="separatorSection">
            <hr id="productDetailsProductDisplaySeparator" class="separator" />
        </div>
        <div id="productDetailsProductDisplaySection" class="formSection row">
            @Html.HiddenFor(m => m.ProductID, new { @id = "productDetailsProductIDField", @class = "tableField col-xs-12 col-sm-12 col-md-12 col-lg-12" })
            <img id="productDetailsProductImage" class="tableImage col-xs-12 col-sm-12 col-md-12 col-lg-12" src="@Model.ProductPicturePath" alt="Produktbild" />
            <div id="productDetailsProductName" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
                @Html.DisplayFor(m => m.ProductName)
            </div>
            <div id="productDetailsProductDescriptionField" class="tableField col-xs-12 col-sm-12 col-md-12 col-lg-12">
                @Html.DisplayFor(m => m.ProductDescription)
            </div>
<!-- define subscription quantity -->
            <a id="productDetailsSubscriptionMinusButton" class="tableButton col-xs-offset-2 col-xs-2 col-sm-offset-2 col-sm-2 col-md-offset-3 col-md-2 col-lg-offset-3 col-lg-2">
                -
            </a>
            @Html.TextBoxFor(m => m.SubscriptionQuantity, new { @id = "productDetailsSubscriptionQuantityField", @class = "tableField col-xs-offset-1 col-xs-2 col-sm-offset-1 col-sm-2 col-md-offset-0 col-md-2 col-lg-offset-0 col-lg-2" placeholder = "0" })
            <a id="productDetailsSubscriptionPlusButton" class="tableButton col-xs-offset-1 col-xs-2 col-sm-offset-1 col-sm-2 col-md-offset-0 col-md-2 col-lg-offset-0 col-lg-2">
                +
            </a>
            @Html.LabelFor(m => m.SubscriptionCadenceCategory, new { @id = "productDetailsSubscriptionCadenceCategoryLabel", @class = "tableLabel" })
            @Html.TextBoxFor(m => m.SubscriptionCadenceCategory, new { @id = "productDetailsSubscriptionCadenceCategoryField", @class= "tableField" })
            @Html.LabelFor(m => m.SubscriptionCadenceValue, new { @id = "productDetailsSubscriptionCadenceValueLabel", @class = "tableLabel" })
            @Html.TextBoxFor(m => m.SubscriptionCadenceValue, new { @id = "productDetailsSubscriptionCadenceValueField", @class= "tableField" })

        </div>

        <div id="productCatalogListPartialMenuSeparatorSection" class="separatorSection">
            <hr id="productCatalogListPartialMenuSeparator" class="separator" />
        </div>
        @Html.ActionLink("zum Warenkorb", "ShowShoppingCart", "", htmlAttributes: new { @class = "formButton col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-3 col-md-6 col-lg-offset-3 col-lg-6" })
    </section>
</div>
<!-- link back to menu -->
<div id="productCatalogReturnToMenuSection" class="linkSection">
    @Html.ActionLink("zurück zum Menü", "Profile", "", htmlAttributes: new { @id = "productCatalogReturnToMenuButton", @class = "link" })
</div>
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
<!-- Google Places -->
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBYK8aBCsb1dFrzXqIgUq07ZwO3w3_fGCs&libraries=places&callback=initAutocomplete" async defer></script>
}

1 个答案:

答案 0 :(得分:1)

注意:由于技术原因,我无法运行此代码。因此,它可能包含未捕获的错误。让我知道这些事情。

因此,这是一个过于完整的示例。 想法如下:

  • 我们称之为索引视图
  • 我们从数据库中获取所有用户,并将列表存储在ViewModel中(如果没有它,我们可以仅通过传递PersonEntity的列表来完成此操作)
  • 我们显示使用HTML表格列出所有人员的视图
  • 当我们单击Details链接时,我们将被发送到DetailRow操作。 person.Id作为GET参数传递。
  • DetailRow视图中,我们查询数据库,但仅请求与作为参数传递的PersonEntity匹配的Id
  • 我们要求实体框架使用Detail方法包括.Include属性。
  • 我们返回获得的结果,该结果将映射到视图模型后成为单个PersonEntity
  • 我们在Person视图中显示返回的DetailRow

我认为粗体字直接回答了您的问题。 在此示例中,我假设您使用的是Entity Framework,否则,您需要将对Context类的调用“转换”为某种DAO,或者如果您是一个肮脏的人,则直接插入SQL。 -)

控制器和数据层的代码(理想情况下,每个类都放在自己的文件中)

public class KenFExample : Controller
{
    // GET
    public IActionResult Index()
    {
        using (Context context = new Context())
        {
            // Get the whole list of basic entries
            IEnumerable<SimplePersonViewModel> rows = context.Persons.Select(r => new SimplePersonViewModel(r));

            // Construct a new view model with these entries
            BaseListingViewModel model = new BaseListingViewModel(rows);

            return View(model);
        }
    }

    public IActionResult DetailRow(int id)
    {
        using (Context context = new Context())
        {
            // Get only the entry that we are interrested in
            PersonEntity row = context.Persons.Include(p => p.Detail).Single(r => r.Id == id);

            // Construct a new view model with this entry
            PersonViewModel model = new PersonViewModel(row);

            return View(model);
        }
    }
}

public class Context : DbContext
{
    public virtual DbSet<PersonEntity> Persons { get; set; }
    public virtual DbSet<DetailEntity> Details { get; set; }
}

public class PersonViewModel
{
    public PersonViewModel(PersonEntity entity)
    {
        Id = entity.Id;
        FirstName = entity.FirstName;
        LastName = entity.LastName;
        IsHandsome = entity.Detail.IsHandsome;
        Address = entity.Detail.Address;
        Email = entity.Detail.Email;
        Phone = entity.Detail.Phone;
    }

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsHandsome { get; set; }
    public string Address { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
}

public class PersonEntity
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public virtual DetailEntity Detail { get; set; }
}

public class DetailEntity
{

    public bool IsHandsome { get; set; }
    public string Address { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public virtual PersonEntity Person { get; set; }

}

public class SimplePersonViewModel
{

    public SimplePersonViewModel(PersonEntity entity)
    {
        Id = entity.Id;
        FirstName = entity.FirstName;
        LastName = entity.LastName;
    }

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class BaseListingViewModel
{
    public BaseListingViewModel(IEnumerable<SimplePersonViewModel> list)
    {
        Rows = list;
    }

    public IEnumerable<SimplePersonViewModel> Rows { get; set; }
}

这是Index.cshtml视图

@model BaseListingViewModel

<table>
    <thead>
    <tr>
        <td>
            Id
        </td>
        <td>
            First name
        </td>
        <td>
            Last name
        </td>
        <td>
            Is handsome
        </td>
        <td>
            Go to details
        </td>
    </tr></thead>
    @foreach (SimplePersonViewModel person in Model.Rows)
    {
        <tr>
            <td>
                @person.Id
            </td>
            <td>
                @person.FirstName
            </td>
            <td>
                @person.LastName
            </td>
            <td>
                <a href="@Url.Action("DetailRow", new {id = person.Id})">Details</a>
            </td>
        </tr>
    }
</table>

这是DetailRow.cshtml视图

@model RelaxationPortal.Controllers.PersonViewModel

Details for @Model.FirstName @Model.LastName (id: @Model.Id)
<br />
Address is @Model.Address and can be contacted using @Model.Phone

@if (Model.IsHandsome)
{
    <span>He <b>IS</b> handsome</span>
}

else
{
    <span>He isn't so handsome</span>
}