(编辑)
我有一个带有products(products)的表,它显示在一个名为productcatalog的视图中,用户可以在该视图中找到products表中的所有产品。我使用的是标准(索引)视图。
我现在想要实现的是这样一个场景:可以选择(单击)目录中的单个产品,并显示产品的详细视图(类似于crud中的标准编辑/详细信息方法)。
然而
,在这个details视图(productdetails)中,我需要增强模型,因为用户将确定变量,如订单数量,这些变量应与产品(主要是productid)中的属性一起发布到新表(lineitems)中,以最终创建订单。
我一直未能做到这一点。不确定我是否需要使用mutliple视图模型或者做一些其他我不知道的花哨的事情。
总之,问题是如何从索引到细节,以及如何从细节到将不同的视图模型发布到某个数据库。所有这些都和英孚有关。
模型:
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; }
}
视图
@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>
}
控制器
// GET: /freshNclean/ProductDetails
public ActionResult ShowProduct(int? id)
{
// define variables
var userID = User.Identity.GetUserId();
DateTime nowUTC = DateTime.Now.ToUniversalTime();
DateTime nowLocal = DateTime.Now.ToLocalTime();
if (id == null)
{
// track user activity: get method includes activity name and timestamp without location
var NOPRODUCTID = new UserActivities
{
UserID = userID,
ActivityName = "ProductDetails_NoProductID",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = "n/a",
ActivityLongitude = "n/a",
ActivityLocation = "n/a"
};
DATADB.UserActivityList.Add(NOPRODUCTID);
DATADB.SaveChanges();
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Products model = DATADB.ProductList.Find(id);
if(model == null)
{
// track user activity: get method includes activity name and timestamp without location
var PRODUCTSMODELFAILURE = new UserActivities
{
UserID = userID,
ActivityName = "ProductDetails_ProductsModelFailure",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = "n/a",
ActivityLongitude = "n/a",
ActivityLocation = "n/a"
};
DATADB.UserActivityList.Add(PRODUCTSMODELFAILURE);
DATADB.SaveChanges();
return HttpNotFound();
}
// track user activity: get method includes activity name and timestamp without location
var LOADED = new UserActivities
{
UserID = userID,
ActivityName = "ProductDetails_Loaded",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = "n/a",
ActivityLongitude = "n/a",
ActivityLocation = "n/a"
};
DATADB.UserActivityList.Add(LOADED);
DATADB.SaveChanges();
return View(model);
}