📜 ⬆️ ⬇️

ASP.NET MVC Lesson 5. Creating a Database Entry

The purpose of the lesson. Track all the way to create a record in the database and output it. Error output. Validation. Mappers. Writing a validation attribute. Captcha Creating data in the database.

Introduction

Finally, go to one of the most important lessons, which will be discussed about the creation of records. Any action on the site, from complex ones, when we fill out a registration form, to simple ones, when we like it, happens as follows:



check in

Make a form for user registration. When registering, the user must recognize the captcha and re-enter the password. But let's start without it. Create a Register method in the UserController and View controller.
public ActionResult Register() { var newUser = new User(); return View(newUser); } 

Create and pass to View a new User object. Since we have only two fields, create a View to fill in:
 @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> } 

')
All these divs, fieldsets and buttons are made in a similar way as described in the bootstrap framework (we will study further).
Let's study the main Html-inserts:
 Html.BeginForm("Register", "User", FormMethod.Post, new { @class = "form-horizontal" }) 

- forms a tag 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 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
  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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

Source: https://habr.com/ru/post/176023/


All Articles