はじめに
最後に、レコードの作成について説明する最も重要なレッスンの1つに進みます。 登録フォームに記入するときの複雑なものから、必要なときに簡単なものまで、サイト上のあらゆるアクションは、次のように発生します。
- サイトへのリクエストの取得\取得
- 承認と認証
- 入力されたデータの妥当性の検証(検証)
- 入力されたデータの検証により、入力されたデータが正しくないことが示された場合、入力するフォームに警告が表示されます。
- 入力されたデータの検証でこのデータが正しいことが示された場合、それらはデータベースに保存され、確認ページが表示されます。
登録
ユーザー登録フォームを作成しましょう。 登録するとき、ユーザーはキャプチャを認識し、パスワードを繰り返す必要があります。 しかし、それなしで始めましょう。 UserControllerおよびViewでRegisterメソッドを作成します。
public ActionResult Register() { var newUser = new User(); return View(newUser); }
新しいユーザーオブジェクトを作成し、ビューに渡します。 フィールドは2つしかないため、入力するビューを作成します。
@using (Html.BeginForm("Register", "User", FormMethod.Post, new { @class = "form-horizontal" })) { <fieldset> <div class="control-group"> <label class="control-label" for="Email"> Email </label> <div class="controls"> @Html.ValidationMessage("Email") @Html.TextBox("Email", Model.Email) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Password </label> <div class="controls"> @Html.ValidationMessage("Password") @Html.Password("Password", Model.Password) </div> </div> <div class="form-actions"> <button type="submit" class="btn btn-primary"> Register </button> @Html.ActionLink("Cancel", "Index", null, null, new { @class = "btn" }) </div> </fieldset> }
これらのすべてのdiv、フィールドセット、およびボタンは、 ブートストラップフレームワークで説明されているように、似たようなもので作成されます(さらに学習します)。
基本的なHTML挿入について学習しましょう。
Html.BeginForm("Register", "User", FormMethod.Post, new { @class = "form-horizontal" })
-タグを作成し
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
-
Dispose()
(using() {}
)
@Html.TextBox("Email", Model.Email)
-(.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not nullLessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs:/// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, — HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email – , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , – MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(“ErrorField”) Html.ValidationSummary(). , , — ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- – .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . – , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email – . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , «» . , « », .. – , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. – . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 – orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, – name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- “image/jpeg” .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons