使用新的(增强的视图模型)编辑的 MVC 索引
MVC index to edit with new (enhanced view model)
(已编辑)
我有一个包含产品 (Products) 的 table,它显示在名为 ProductCatalog 的视图中,用户可以在其中找到产品 table 中的所有产品。我为此使用标准(索引)视图。
我现在想要实现的是可以从目录中选择(单击)单个产品并显示该产品的详细视图的场景(类似于 CRUD 中的标准 Edit/Details 方法) . 但是,在此详细信息视图 (ProductDetails) 中,我需要增强模型,因为用户会确定变量,例如应该 posted 到新的 [=34] 的订单数量=] (LineItems) 以及产品的属性(主要是 ProductID)以最终创建订单。
我一直没能做到这一点。不确定我是否需要使用多个视图模型或做一些我不知道的其他花哨的东西。
所以总而言之,问题是如何从索引到详细信息以及如何从详细信息到 post 某个数据库的不同视图模型。所有这一切都在 EF 中。
型号:
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);
}
注意:由于技术原因,我无法 运行 此代码。因此,它可能包含未捕获的错误。让我知道任何此类事情。
所以,这是一个过于完整的示例。
思路如下:
- 我们调用索引视图
- 我们从数据库中获取所有用户并将列表存储在我们的 ViewModel 中(如果没有它,我们可以只传递
PersonEntity
的列表)
- 我们显示使用 HTML table
列出所有人员的视图
- 当我们单击
Details
link 时,我们将转到 DetailRow
操作。 person.Id
作为 GET 参数传递。
- 在
DetailRow
视图中,我们查询数据库,但只请求与作为参数传递的 Id
相匹配的 PersonEntity
。
- 我们要求 entity framework 使用
.Include
方法包含 Detail
属性。
- 我们return我们得到的结果,映射到视图模型后将是一个
PersonEntity
。
- 我们在
DetailRow
视图中显示 returned Person
粗线是我认为直接回答你问题的那些。
在此示例中,我假设您使用了 Entity Framework,否则您将需要 "translate" 对 Context
class 的调用对某种 DAO 或内联SQL 如果你是个肮脏的人 ;-)
控制器和数据层的代码(理想情况下,每个 class 都在其自己的文件中)
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>
}
(已编辑) 我有一个包含产品 (Products) 的 table,它显示在名为 ProductCatalog 的视图中,用户可以在其中找到产品 table 中的所有产品。我为此使用标准(索引)视图。
我现在想要实现的是可以从目录中选择(单击)单个产品并显示该产品的详细视图的场景(类似于 CRUD 中的标准 Edit/Details 方法) . 但是,在此详细信息视图 (ProductDetails) 中,我需要增强模型,因为用户会确定变量,例如应该 posted 到新的 [=34] 的订单数量=] (LineItems) 以及产品的属性(主要是 ProductID)以最终创建订单。
我一直没能做到这一点。不确定我是否需要使用多个视图模型或做一些我不知道的其他花哨的东西。
所以总而言之,问题是如何从索引到详细信息以及如何从详细信息到 post 某个数据库的不同视图模型。所有这一切都在 EF 中。
型号:
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);
}
注意:由于技术原因,我无法 运行 此代码。因此,它可能包含未捕获的错误。让我知道任何此类事情。
所以,这是一个过于完整的示例。 思路如下:
- 我们调用索引视图
- 我们从数据库中获取所有用户并将列表存储在我们的 ViewModel 中(如果没有它,我们可以只传递
PersonEntity
的列表) - 我们显示使用 HTML table 列出所有人员的视图
- 当我们单击
Details
link 时,我们将转到DetailRow
操作。person.Id
作为 GET 参数传递。 - 在
DetailRow
视图中,我们查询数据库,但只请求与作为参数传递的Id
相匹配的PersonEntity
。 - 我们要求 entity framework 使用
.Include
方法包含Detail
属性。 - 我们return我们得到的结果,映射到视图模型后将是一个
PersonEntity
。 - 我们在
DetailRow
视图中显示 returnedPerson
粗线是我认为直接回答你问题的那些。
在此示例中,我假设您使用了 Entity Framework,否则您将需要 "translate" 对 Context
class 的调用对某种 DAO 或内联SQL 如果你是个肮脏的人 ;-)
控制器和数据层的代码(理想情况下,每个 class 都在其自己的文件中)
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>
}