Bölüm 9: Kayıt ve Kasa İşlemleri
MVC Müzik Deposu, web geliştirme için ASP.NET MVC ve Visual Studio'yu kullanmayı adım adım tanıtır ve açıklayan bir öğretici uygulamasıdır.
MVC Music Store, müzik albümlerini çevrimiçi olarak satan ve temel site yönetimi, kullanıcı oturum açma ve alışveriş sepeti işlevlerini uygulayan basit bir örnek mağaza uygulamasıdır.
Bu öğretici serisi, ASP.NET MVC Müzik Deposu örnek uygulamasını derlemek için atılan tüm adımların ayrıntılarını içerir. Bölüm 9, Kayıt ve Ödeme'ye değinmektedir.
Bu bölümde, alışveriş yapanın adresini ve ödeme bilgilerini toplayacak bir CheckoutController oluşturacağız. Kullanıcıların kullanıma almadan önce sitemize kaydolmasını zorunlu kılarız, bu nedenle bu denetleyici için yetkilendirme gerekir.
Kullanıcılar, "Alışverişi Tamamla" düğmesine tıklayarak alışveriş sepetlerinden ödeme işlemine gider.
Kullanıcı oturum açmamışsa, oturum açması istenir.
Oturum başarıyla açıldıktan sonra kullanıcıya Adres ve Ödeme görünümü gösterilir.
Formu doldurup siparişi gönderdikten sonra sipariş onay ekranı gösterilir.
Mevcut olmayan bir siparişi veya size ait olmayan bir siparişi görüntülemeye çalıştığınızda Hata görünümü gösterilir.
Alışveriş Sepetini Geçirme
Alışveriş işlemi anonim olsa da, kullanıcı Kullanıma Al düğmesine tıkladığında kaydolması ve oturum açması gerekir. Kullanıcılar, alışveriş sepeti bilgilerini ziyaretler arasında tutmamızı bekler, bu nedenle kayıt veya oturum açma işlemlerini tamamlayan bir kullanıcıyla alışveriş sepeti bilgilerini ilişkilendirmemiz gerekir.
ShoppingCart sınıfımız zaten geçerli sepetteki tüm öğeleri bir kullanıcı adıyla ilişkilendirecek bir yönteme sahip olduğundan, bunu yapmak gerçekten çok basittir. Yalnızca bir kullanıcı kaydı veya oturum açmayı tamamladığında bu yöntemi çağırmamız gerekir.
Üyelik ve Yetkilendirmeyi ayarlarken eklediğimiz AccountController sınıfını açın. MvcMusicStore.Models'e başvuran bir using deyimi ekleyin ve ardından aşağıdaki MigrateShoppingCart yöntemini ekleyin:
private void MigrateShoppingCart(string UserName)
{
// Associate shopping cart items with logged-in user
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.MigrateCart(UserName);
Session[ShoppingCart.CartSessionKey] = UserName;
}
Ardından, aşağıda gösterildiği gibi Kullanıcı doğrulandıktan sonra MigrateShoppingCart'ı çağırmak için LogOn gönderi eylemini değiştirin:
//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
MigrateShoppingCart(model.UserName);
FormsAuthentication.SetAuthCookie(model.UserName,
model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1
&& returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") &&
!returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Kullanıcı hesabı başarıyla oluşturulduktan hemen sonra Kayıt sonrası eyleminde de aynı değişikliği yapın:
//
// POST: /Account/Register
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email,
"question", "answer", true, null, out
createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
MigrateShoppingCart(model.UserName);
FormsAuthentication.SetAuthCookie(model.UserName, false /*
createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Hepsi bu kadar- artık başarılı bir kayıt veya oturum açma işleminden sonra anonim bir alışveriş sepeti otomatik olarak bir kullanıcı hesabına aktarılacak.
CheckoutController Oluşturma
Denetleyiciler klasörüne sağ tıklayın ve Boş denetleyici şablonunu kullanarak CheckoutController adlı projeye yeni bir Denetleyici ekleyin.
İlk olarak, kullanıcıların kullanıma almadan önce kaydolmasını istemek için Denetleyici sınıfı bildiriminin üzerine Authorize özniteliğini ekleyin:
namespace MvcMusicStore.Controllers
{
[Authorize]
public class CheckoutController : Controller
Not: Bu, daha önce StoreManagerController'da yaptığımız değişikliğe benzer, ancak bu durumda Kullanıcının Yönetici rolünde olması için Authorize özniteliği gerekir. Kullanıma Alma Denetleyicisi'nde kullanıcının oturum açmasını zorunlu kılıyoruz ancak yönetici olmasını istemiyoruz.
Kolaylık olması için bu öğreticide ödeme bilgileriyle ilgilenmeyeceğiz. Bunun yerine kullanıcıların tanıtım kodu kullanarak kullanıma almalarına izin veririz. Bu promosyon kodunu PromoCode adlı bir sabit kullanarak depolayacağız.
StoreController'da olduğu gibi, storeDB adlı MusicStoreEntities sınıfının bir örneğini barındıracak bir alan bildireceğiz. MusicStoreEntities sınıfından yararlanmak için MvcMusicStore.Models ad alanı için bir using deyimi eklememiz gerekir. Kullanıma Alma denetleyicimizin üst kısmında aşağıda görünür.
using System;
using System.Linq;
using System.Web.Mvc;
using MvcMusicStore.Models;
namespace MvcMusicStore.Controllers
{
[Authorize]
public class CheckoutController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities();
const string PromoCode = "FREE";
CheckoutController aşağıdaki denetleyici eylemlerine sahip olacaktır:
AddressAndPayment (GET yöntemi), kullanıcının bilgilerini girmesine izin veren bir form görüntüler.
AddressAndPayment (POST yöntemi), girişi doğrular ve sırayı işler.
Kullanıcı kullanıma alma işlemini başarıyla tamamladıktan sonra Tamamlandı ifadesi gösterilir. Bu görünüm, onay olarak kullanıcının sipariş numarasını içerir.
İlk olarak, Dizin denetleyicisi eylemini (denetleyiciyi oluştururken oluşturulan) AddressAndPayment olarak yeniden adlandıralım. Bu denetleyici eylemi yalnızca kullanıma alma formunu görüntüler, bu nedenle herhangi bir model bilgisi gerektirmez.
//
// GET: /Checkout/AddressAndPayment
public ActionResult AddressAndPayment()
{
return View();
}
AddressAndPayment POST yöntemimiz, StoreManagerController'da kullandığımız deseni izler: form gönderimini kabul etmeye ve siparişi tamamlamaya çalışır ve başarısız olursa formu yeniden görüntüler.
Form girişini doğruladıktan sonra Sipariş için doğrulama gereksinimlerimizi karşılıyorsa PromoCode form değerini doğrudan denetleyeceğiz. Her şeyin doğru olduğunu varsayarsak, güncelleştirilmiş bilgileri siparişle birlikte kaydeder, ShoppingCart nesnesine sipariş işlemini tamamlamasını söyler ve Tamamla eylemine yönlendiririz.
//
// POST: /Checkout/AddressAndPayment
[HttpPost]
public ActionResult AddressAndPayment(FormCollection values)
{
var order = new Order();
TryUpdateModel(order);
try
{
if (string.Equals(values["PromoCode"], PromoCode,
StringComparison.OrdinalIgnoreCase) == false)
{
return View(order);
}
else
{
order.Username = User.Identity.Name;
order.OrderDate = DateTime.Now;
//Save Order
storeDB.Orders.Add(order);
storeDB.SaveChanges();
//Process the order
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(order);
return RedirectToAction("Complete",
new { id = order.OrderId });
}
}
catch
{
//Invalid - redisplay with errors
return View(order);
}
}
Kullanıma alma işlemi başarıyla tamamlandıktan sonra kullanıcılar Tam denetleyici eylemine yönlendirilir. Bu eylem, sipariş numarasını onay olarak göstermeden önce siparişin gerçekten oturum açmış kullanıcıya ait olduğunu doğrulamak için basit bir denetim gerçekleştirir.
//
// GET: /Checkout/Complete
public ActionResult Complete(int id)
{
// Validate customer owns this order
bool isValid = storeDB.Orders.Any(
o => o.OrderId == id &&
o.Username == User.Identity.Name);
if (isValid)
{
return View(id);
}
else
{
return View("Error");
}
}
Not: Proje başlatıldığında Hata görünümü bizim için /Views/Shared klasöründe otomatik olarak oluşturuldu.
CheckoutController kodunun tamamı aşağıdaki gibidir:
using System;
using System.Linq;
using System.Web.Mvc;
using MvcMusicStore.Models;
namespace MvcMusicStore.Controllers
{
[Authorize]
public class CheckoutController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities();
const string PromoCode = "FREE";
//
// GET: /Checkout/AddressAndPayment
public ActionResult AddressAndPayment()
{
return View();
}
//
// POST: /Checkout/AddressAndPayment
[HttpPost]
public ActionResult AddressAndPayment(FormCollection values)
{
var order = new Order();
TryUpdateModel(order);
try
{
if (string.Equals(values["PromoCode"], PromoCode,
StringComparison.OrdinalIgnoreCase) == false)
{
return View(order);
}
else
{
order.Username = User.Identity.Name;
order.OrderDate = DateTime.Now;
//Save Order
storeDB.Orders.Add(order);
storeDB.SaveChanges();
//Process the order
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(order);
return RedirectToAction("Complete",
new { id = order.OrderId });
}
}
catch
{
//Invalid - redisplay with errors
return View(order);
}
}
//
// GET: /Checkout/Complete
public ActionResult Complete(int id)
{
// Validate customer owns this order
bool isValid = storeDB.Orders.Any(
o => o.OrderId == id &&
o.Username == User.Identity.Name);
if (isValid)
{
return View(id);
}
else
{
return View("Error");
}
}
}
}
AddressAndPayment görünümünü ekleme
Şimdi AddressAndPayment görünümünü oluşturalım. AddressAndPayment denetleyici eylemlerinden birine sağ tıklayın ve aşağıda gösterildiği gibi, kesinlikle Sipariş olarak yazılan ve Düzenle şablonunu kullanan AddressAndPayment adlı bir görünüm ekleyin.
Bu görünümde StoreManagerEdit görünümünü oluştururken incelediğimiz iki teknik kullanılır:
- Sipariş modelinin form alanlarını görüntülemek için Html.EditorForModel() kullanacağız
- Doğrulama özniteliklerine sahip bir Order sınıfını kullanarak doğrulama kuralları kullanacağız
Başlangıç olarak form kodunu Html.EditorForModel() kullanacak şekilde güncelleştireceğiz ve ardından Promosyon Kodu için ek bir metin kutusu ekleyeceğiz. AddressAndPayment görünümünün tam kodu aşağıda gösterilmiştir.
@model MvcMusicStore.Models.Order
@{
ViewBag.Title = "Address And Payment";
}
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
type="text/javascript"></script>
@using (Html.BeginForm()) {
<h2>Address And Payment</h2>
<fieldset>
<legend>Shipping Information</legend>
@Html.EditorForModel()
</fieldset>
<fieldset>
<legend>Payment</legend>
<p>We're running a promotion: all music is free
with the promo code: "FREE"</p>
<div class="editor-label">
@Html.Label("Promo Code")
</div>
<div class="editor-field">
@Html.TextBox("PromoCode")
</div>
</fieldset>
<input type="submit" value="Submit Order" />
}
Sipariş için doğrulama kuralları tanımlama
Artık görünümümüz ayarlandığından, Daha önce Albüm modeli için yaptığımız gibi Sipariş modelimiz için doğrulama kurallarını ayarlayacağız. Models klasörüne sağ tıklayın ve Order adlı bir sınıf ekleyin. Daha önce Albüm için kullandığımız doğrulama özniteliklerine ek olarak, kullanıcının e-posta adresini doğrulamak için Normal İfade de kullanacağız.
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace MvcMusicStore.Models
{
[Bind(Exclude = "OrderId")]
public partial class Order
{
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[ScaffoldColumn(false)]
public System.DateTime OrderDate { get; set; }
[ScaffoldColumn(false)]
public string Username { get; set; }
[Required(ErrorMessage = "First Name is required")]
[DisplayName("First Name")]
[StringLength(160)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
[DisplayName("Last Name")]
[StringLength(160)]
public string LastName { get; set; }
[Required(ErrorMessage = "Address is required")]
[StringLength(70)]
public string Address { get; set; }
[Required(ErrorMessage = "City is required")]
[StringLength(40)]
public string City { get; set; }
[Required(ErrorMessage = "State is required")]
[StringLength(40)]
public string State { get; set; }
[Required(ErrorMessage = "Postal Code is required")]
[DisplayName("Postal Code")]
[StringLength(10)]
public string PostalCode { get; set; }
[Required(ErrorMessage = "Country is required")]
[StringLength(40)]
public string Country { get; set; }
[Required(ErrorMessage = "Phone is required")]
[StringLength(24)]
public string Phone { get; set; }
[Required(ErrorMessage = "Email Address is required")]
[DisplayName("Email Address")]
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",
ErrorMessage = "Email is is not valid.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[ScaffoldColumn(false)]
public decimal Total { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
}
Formu eksik veya geçersiz bilgilerle gönderme girişiminde artık istemci tarafı doğrulaması kullanılarak hata iletisi gösterilir.
Tamam, ödeme süreci için zor işlerin çoğunu yaptık; Bitirmemiz gereken birkaç şey var. İki basit görünüm eklememiz ve oturum açma işlemi sırasında sepet bilgilerinin teslimini yapmamız gerekiyor.
Kullanıma Alma Tamamlandı görünümünü ekleme
Yalnızca Sipariş Kimliğini görüntülemesi gerektiğinden, Kullanıma Alma Tamamlandı görünümü oldukça basittir. Denetleyiciyi tamamla eylemine sağ tıklayın ve tam olarak int olarak yazılan Complete adlı bir görünüm ekleyin.
Şimdi aşağıda gösterildiği gibi Sipariş Kimliğini görüntülemek için görünüm kodunu güncelleştireceğiz.
@model int
@{
ViewBag.Title = "Checkout Complete";
}
<h2>Checkout Complete</h2>
<p>Thanks for your order! Your order number is: @Model</p>
<p>How about shopping for some more music in our
@Html.ActionLink("store",
"Index", "Home")
</p>
Hata görünümünü güncelleştirme
Varsayılan şablon, sitenin başka bir yerinde yeniden kullanılabilmesi için Paylaşılan görünümler klasöründe bir Hata görünümü içerir. Bu Hata görünümü çok basit bir hata içeriyor ve site düzenimizi kullanmadığından güncelleştireceğiz.
Bu genel bir hata sayfası olduğundan içerik çok basittir. Kullanıcı eylemini yeniden denemek istiyorsa, geçmişteki bir önceki sayfaya gitmek için bir ileti ve bağlantı ekleyeceğiz.
@{
ViewBag.Title = "Error";
}
<h2>Error</h2>
<p>We're sorry, we've hit an unexpected error.
<a href="javascript:history.go(-1)">Click here</a>
if you'd like to go back and try that again.</p>
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin