рдкрд╛рда рдХрд╛ рдЙрджреНрджреЗрд╢реНрдпред рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ рдЙрд╕рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдмрдирд╛рдиреЗ рдХреЗ рдкреВрд░реЗ рд░рд╛рд╕реНрддреЗ рдХреЛ рдЯреНрд░реИрдХ рдХрд░реЗрдВред рддреНрд░реБрдЯрд┐ рдЖрдЙрдЯрдкреБрдЯред рдорд╛рдиреНрдпрдХрд░рдгред рдорд╛рдирдЪрд┐рддреНрд░рдХрд╛рд░реЛрдВред рд╕рддреНрдпрд╛рдкрди рд╡рд┐рд╢реЗрд╖рддрд╛ рд▓рд┐рдЦрдирд╛ред рдХреИрдкреНрдЪрд╛ред рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рдмрдирд╛рдирд╛ред
рдкрд░рд┐рдЪрдп
рдЕрдВрдд рдореЗрдВ, рд╣рдо рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкрд╛рдареЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд░рд┐рдХреЙрд░реНрдб рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред рд╕рд╛рдЗрдЯ рдкрд░ рдХреЛрдИ рднреА рдХрд╛рд░реНрд░рд╡рд╛рдИ, рдЬрдм рд╣рдо рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЬрдЯрд┐рд▓ рд╕реЗ рдЬрдЯрд┐рд▓ рдкрдВрдЬреАрдХрд░рдг рдлреЙрд░реНрдо рднрд░рддреЗ рд╣реИрдВ, рдпрд╣ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реЛрддрд╛ рд╣реИ:
- рдкреЛрд╕реНрдЯ \ _ рд╕рд╛рдЗрдЯ рдкрд░ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
- рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдФрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг
- рд╢реБрджреНрдзрддрд╛ рдХреЗ рд▓рд┐рдП рджрд░реНрдЬ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ (рд╕рддреНрдпрд╛рдкрди) рдХреА рдорд╛рдиреНрдпрддрд╛
- рдпрджрд┐ рджрд░реНрдЬ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреЗ рд╕рддреНрдпрд╛рдкрди рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдбреЗрдЯрд╛ рдЧрд▓рдд рд╣реИ, рддреЛ рднрд░реЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдлреЙрд░реНрдо рдореЗрдВ рдПрдХ рдЪреЗрддрд╛рд╡рдиреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред
- рдпрджрд┐ рджрд░реНрдЬ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреЗ рд╕рддреНрдпрд╛рдкрди рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдбреЗрдЯрд╛ рд╕рд╣реА рд╣реИ, рддреЛ рд╡реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рд╣реЗрдЬреЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдкреБрд╖реНрдЯрд┐рдХрд░рдг рдкреГрд╖реНрда рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдкрдВрдЬреАрдХрд░рдг
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрдВрдЬреАрдХрд░рдг рдлреЙрд░реНрдо рдмрдирд╛рддреЗ рд╣реИрдВред рдкрдВрдЬреАрдХрд░рдг рдХрд░рддреЗ рд╕рдордп, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреИрдкреНрдЪрд╛ рдХреЛ рдкрд╣рдЪрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рджреЛрд╣рд░рд╛рдирд╛ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрд┐рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред UserController рдФрд░ рджреГрд╢реНрдп рдореЗрдВ рд░рдЬрд┐рд╕реНрдЯрд░ рд╡рд┐рдзрд┐ рдмрдирд╛рдПрдБред
public ActionResult Register() { var newUser = new User(); return View(newUser); }
рдирдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рджреЗрдЦреЗрдВ рдФрд░ рдмрдирд╛рдПрдВ рдФрд░ рдкрд╛рд╕ рдХрд░реЗрдВред рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рджреЛ рдлрд╝реАрд▓реНрдб рд╣реИрдВ, рднрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреГрд╢реНрдп рдмрдирд╛рдПрдВ:
@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> }
рдЗрди рд╕рднреА divs, рдлрд╝реАрд▓реНрдбреНрд╕ рдФрд░ рдмрдЯрдиреЛрдВ рдХреЛ рд╕рдорд╛рдирддрд╛ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐
рдмреВрдЯрд╕реНрдЯреНрд░реИрдк рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИ (рд╣рдо рдЖрдЧреЗ рдЕрдзреНрдпрдпрди рдХрд░реЗрдВрдЧреЗ)ред
рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рдореВрд▓ HTML рдЖрд╡реЗрд╖рдг:
Html.BeginForm("Register", "User", FormMethod.Post, new { @class = "form-horizontal" })
- рдПрдХ рдЯреИрдЧ рдмрдирд╛рддрд╛ рд╣реИ
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :
, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :
, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:
, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:
5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :
2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:
. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:
User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not null LessonProjectDb.dbml
User Server Explorer SqlRepository/User.cs UpdateUser():
public bool UpdateUser(User instance) { User cache = Db.Users.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Birthdate = instance.Birthdate; cache.AvatarPath = instance.AvatarPath; cache.Email = instance.Email; Db.Users.Context.SubmitChanges(); return true; } return false; }
UserView Bithdate. .
:

. тАУ . Html ( ) DropDownList, .
:
@Html.DropDownList(string name, IEnumerable selectList)
SelectListItem:
public class SelectListItem { public SelectListItem(); public bool Selected { get; set; } public string Text { get; set; } public string Value { get; set; } }
, , 1 - apple, 2 тАУ orange (), 3 - banana :
public IEnumerable<SelectListItem> SelectFruit { get { yield return new SelectListItem() { Value = "1", Text = "apple", Selected = false }; yield return new SelectListItem() { Value = "2", Text = "orange", Selected = true }; yield return new SelectListItem() { Value = "3", Text = "banana", Selected = false }; } }
DropDownList()
, тАУ name, Value () .
C :
public int BirthdateDay { get; set; } public int BirthdateMonth { get; set; } public int BirthdateYear { get; set; } public IEnumerable<SelectListItem> BirthdateDaySelectList { get { for (int i = 1; i < 32; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateDay == i }; } } } public IEnumerable<SelectListItem> BirthdateMonthSelectList { get { for (int i = 1; i < 13; i++) { yield return new SelectListItem { Value = i.ToString(), Text = new DateTime(2000, i, 1).ToString("MMMM"), Selected = BirthdateMonth == i }; } } } public IEnumerable<SelectListItem> BirthdateYearSelectList { get { for (int i = 1910; i < DateTime.Now.Year; i++) { yield return new SelectListItem { Value = i.ToString(), Text = i.ToString(), Selected = BirthdateYear == i }; } } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Birth date </label> <div class="controls"> @Html.DropDownList("BirthdateDay", Model.BirthdateDaySelectList) @Html.DropDownList("BirthdateMonth", Model.BirthdateMonthSelectList) @Html.DropDownList("BirthdateYear", Model.BirthdateYearSelectList) </div> </div>
- point . , UserView:


User. (/Mappers/CommonMapper.cs):
Mapper.CreateMap<User, UserView>() .ForMember(dest => dest.BirthdateDay, opt => opt.MapFrom(src => src.Birthdate.Day)) .ForMember(dest => dest.BirthdateMonth, opt => opt.MapFrom(src => src.Birthdate.Month)) .ForMember(dest => dest.BirthdateYear, opt => opt.MapFrom(src =>src.Birthdate.Year)); Mapper.CreateMap<UserView, User>() .ForMember(dest => dest.Birthdate, opt => opt.MapFrom(src => new DateTime(src.BirthdateYear, src.BirthdateMonth, src.BirthdateDay)));
BirthdateDay, BirthdateMonth, BirthdateYear Birthdate .
Captcha
, , . . . , .
Tools/CaptchaImage.cs: /// <summary> /// /// </summary> public class CaptchaImage { public const string CaptchaValueKey = "CaptchaImageText"; public string Text { get { return text; } } public Bitmap Image { get { return image; } } public int Width { get { return width; } } public int Height { get { return height; } } // Internal properties. private string text; private int width; private int height; private string familyName; private Bitmap image; // For generating random numbers. private Random random = new Random(); public CaptchaImage(string s, int width, int height) { text = s; SetDimensions(width, height); GenerateImage(); } public CaptchaImage(string s, int width, int height, string familyName) { text = s; SetDimensions(width, height); SetFamilyName(familyName); GenerateImage(); } // ==================================================================== // This member overrides Object.Finalize. // ==================================================================== ~CaptchaImage() { Dispose(false); } // ==================================================================== // Releases all resources used by this object. // ==================================================================== public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } // ==================================================================== // Custom Dispose method to clean up unmanaged resources. // ==================================================================== protected virtual void Dispose(bool disposing) { if (disposing) // Dispose of the bitmap. image.Dispose(); } // ==================================================================== // Sets the image aWidth and aHeight. // ==================================================================== private void SetDimensions(int aWidth, int aHeight) { // Check the aWidth and aHeight. if (aWidth <= 0) throw new ArgumentOutOfRangeException("aWidth", aWidth, "Argument out of range, must be greater than zero."); if (aHeight <= 0) throw new ArgumentOutOfRangeException("aHeight", aHeight, "Argument out of range, must be greater than zero."); width = aWidth; height = aHeight; } // ==================================================================== // Sets the font used for the image text. // ==================================================================== private void SetFamilyName(string aFamilyName) { // If the named font is not installed, default to a system font. try { Font font = new Font(aFamilyName, 12F); familyName = aFamilyName; font.Dispose(); } catch (Exception) { familyName = FontFamily.GenericSerif.Name; } } // ==================================================================== // Creates the bitmap image. // ==================================================================== private void GenerateImage() { // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); // Create a graphics object for drawing. Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); // Fill in the background. HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White); g.FillRectangle(hatchBrush, rect); // Set up the text font. SizeF size; float fontSize = rect.Height + 1; Font font; // Adjust the font size until the text fits within the image. do { fontSize--; font = new Font(familyName, fontSize, FontStyle.Bold); size = g.MeasureString(text, font); } while (size.Width > rect.Width); // Set up the text format. StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; // Create a path using the text and warp it randomly. GraphicsPath path = new GraphicsPath(); path.AddString(text, font.FontFamily, (int)font.Style, font.Size, rect, format); float v = 4F; PointF[] points = { new PointF(random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, random.Next(rect.Height) / v), new PointF(random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v), new PointF(rect.Width - random.Next(rect.Width) / v, rect.Height - random.Next(rect.Height) / v) }; Matrix matrix = new Matrix(); matrix.Translate(0F, 0F); path.Warp(points, rect, matrix, WarpMode.Perspective, 0F); // Draw the text. hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray); g.FillPath(hatchBrush, path); // Add some random noise. int m = Math.Max(rect.Width, rect.Height); for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++) { int x = random.Next(rect.Width); int y = random.Next(rect.Height); int w = random.Next(m / 50); int h = random.Next(m / 50); g.FillEllipse(hatchBrush, x, y, w, h); } // Clean up. font.Dispose(); hatchBrush.Dispose(); g.Dispose(); // Set the image. image = bitmap; } }
, Image , ( ) GenerateImage().
UserController.Captcha():
public ActionResult Captcha() { Session[CaptchaImage.CaptchaValueKey] = new Random(DateTime.Now.Millisecond).Next(1111, 9999).ToString(); var ci = new CaptchaImage(Session[CaptchaImage.CaptchaValueKey].ToString(), 211, 50, "Arial"); // Change the response headers to output a JPEG image. this.Response.Clear(); this.Response.ContentType = "image/jpeg"; // Write the image to the response stream in JPEG format. ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg); // Dispose of the CAPTCHA image object. ci.Dispose(); return null; }
:
1111 9999. ci CatchaImage header mime- http- тАЬimage/jpegтАЭ .. jpeg. bitmap ImageFormat.Jpeg Bitmap null,
Register.cshtml (/Areas/Default/View/User/Register.cshtml):
<label class="control-label" for="FirstName"> <img src="@Url.Action("Captcha", "User")" alt="captcha" /> </label>
(/Areas/Default/Controllers/UserController.cs):
if (userView.Captcha != (string)Session[CaptchaImage.CaptchaValueKey]) { ModelState.AddModelError("Captcha", " "); }
, . , :
if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); Repository.CreateUser(user); return RedirectToAction("Index"); }
https://bitbucket.org/chernikov/lessons
Dispose()
( using() {}
)
@Html.TextBox("Email", Model.Email)
- (.. Email )
@Html.ValidationMessage("Password")
-
@Html.Password("Password", Model.Password)
-
Register Http- POST ( FormMethod.Post
Email=&Password=.
Register, User, HttpPost, тАФ HttpGet. , , :
[HttpGet] public ActionResult Register() { var newUser = new User(); return View(newUser); } [HttpPost] public ActionResult Register(User user) { return View(user); }
Register , :

, Email Password , (default).
2 ( ), User partial class:
public partial class User { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } }
View:
<div class="control-group"> <label class="control-label" for="FirstName"> Confirm Password </label> <div class="controls"> @Html.ValidationMessage("ConfirmPassword") @Html.Password("ConfirmPassword", Model.ConfirmPassword) </div> </div> <div class="control-group"> <label class="control-label" for="FirstName"> Captcha </label> </div> <div class="control-group"> <label class="control-label" for="FirstName"> 1234 </label> <div class="controls"> @Html.ValidationMessage("Captcha") @Html.TextBox("Captcha", Model.Captcha) </div> </div>
, 1234.
:
email Email тАУ , .. Email - 1234
- , .
IValidatableObject
User - partial, IValidatableObject , , , System.Component.DataAnnotation. , , тАУ MVC. .
User:
public partial class User : IValidatableObject { public static string GetActivateUrl() { return Guid.NewGuid().ToString("N"); } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // Email if (string.IsNullOrWhiteSpace(Email)) { yield return new ValidationResult(" email", new string[] {"Email"}); } // Email var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(Email); if (!(match.Success && match.Length == Email.Length)) { yield return new ValidationResult(" email", new string[] { "Email" }); } // if (string.IsNullOrWhiteSpace(Password)) { yield return new ValidationResult(" ", new string[] { "Password" }); } // if (Password != ConfirmPassword) { yield return new ValidationResult(" ", new string[] { "ConfirmPassword" }); } } }
4 6 , , .
, :

, .
: Html.ValidationMessage(тАЬErrorFieldтАЭ) Html.ValidationSummary(). , , тАФ ( ) .
Email (/Areas/Default/UserController.cs:Register):
if (user.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, user.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); }
:

, , , , :
User , , , , . .. , : , , . Model- Controller- тАУ .
, , User, . UserView Models/ViewModels:
public class UserView { public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
Automapping
, , . , User, , - UserView User , . тАУ , , Update[Table] . object-to-object.
, automapper ( http://automapper.org/ ). , , , , .
Automapper:
Install-Package AutoMapper
, + Ninject, .
/Mappers:
public interface IMapper { object Map(object source, Type sourceType, Type destinationType); }
:
public class CommonMapper : IMapper { static CommonMapper() { Mapper.CreateMap<User, UserView>(); Mapper.CreateMap<UserView, User>(); } public object Map(object source, Type sourceType, Type destinationType) { return Mapper.Map(source, sourceType, destinationType); } }
( -) (/App_Start/NinjectWebCommon.cs):
kernel.Bind<IMapper>().To<CommonMapper>().InSingletonScope();
BaseController (/Controllers/BaseController.cs):
public abstract class BaseController : Controller { [Inject] public IRepository Repository { get; set; } [Inject] public IMapper ModelMapper { get; set; } }
UserController ( View) UserView:
[HttpGet] public ActionResult Register() { var newUserView = new UserView(); return View(newUserView); } [HttpPost] public ActionResult Register(UserView userView) { if (userView.Captcha != "1234") { ModelState.AddModelError("Captcha", " "); } var anyUser = Repository.Users.Any(p => string.Compare(p.Email, userView.Email) == 0); if (anyUser) { ModelState.AddModelError("Email", " email "); } if (ModelState.IsValid) { var user = (User)ModelMapper.Map(userView, typeof(UserView), typeof(User)); //TODO: } return View(userView); }
Register.cshtml :
@model LessonProject.Models.ViewModels.UserView
UserView .
:
using System.ComponentModel.DataAnnotations; public class UserView { public int ID { get; set; } [Required(ErrorMessage=" email")] public string Email { get; set; } [Required(ErrorMessage=" ")] public string Password { get; set; } [Compare("Password", ErrorMessage=" ")] public string ConfirmPassword { get; set; } public string Captcha { get; set; } public string AvatarPath { get; set; } }
:

5 6 . , email тАУ . -, email:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ValidEmailAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) { return true; } if (!(value is string)) { return true; } var source = value as string; if (string.IsNullOrWhiteSpace(source)) { return true; } var regex = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.Compiled); var match = regex.Match(source); return (match.Success && match.Length == source.Length); } }
, , , ┬л┬╗ . , ┬л ┬╗, .. тАУ , . , , . , .
: DataAnnotationsExtensions, ( http://dataannotationsextensions.org/ )
. , , , .
. Birthdate datetime null.
: , , :

2012-1-1
Birthdate datetime not 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
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