ASP.NET MVC рдореЗрдВ, рдореЗрдЯрд╛рдбреЗрдЯрд╛ - рдЧреБрдг рдЬреЛ рдПрдХ рдореЙрдбрд▓ рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ - рджреЛрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рд░реНрдХрдЕрдк рдХреА рдкреАрдврд╝реА (рдХреНрд╖реЗрддреНрд░ рдХрд╛ рдирд╛рдо, рдЗрд╕рдХреЗ рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░ рдЗрддреНрдпрд╛рджрд┐ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ) рдФрд░ рдбреЗрдЯрд╛ рд╕рддреНрдпрд╛рдкрди (рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдореЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ) рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо рд╕рд╢рд░реНрдд рд░реВрдк рд╕реЗ рд╕рддреНрдпрд╛рдкрди рдХреЗ 2 рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
- рдЧреНрд░рд╛рд╣рдХ рд╕рддреНрдпрд╛рдкрди
- рд╕рд░реНрд╡рд░ рд╕рддреНрдпрд╛рдкрди
рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рддреНрдпрд╛рдкрди рдЕрдЪреНрдЫрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рддреБрд░рдВрдд рдлрд╝реАрд▓реНрдб рднрд░рдиреЗ рдореЗрдВ рдХреА рдЧрдИ рдЧрд▓рддрд┐рдпреЛрдВ рдХреЛ рджреЗрдЦрддрд╛ рд╣реИ рдФрд░ рд╕рд░реНрд╡рд░ (рд╡рд┐рдиреАрдд рд╕рддреНрдпрд╛рдкрди) рдХреЛ рдбреЗрдЯрд╛ рднреЗрдЬреЗ рдмрд┐рдирд╛ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рддреНрдпрд╛рдкрди рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реИред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реИ?рдорд╛рд░реНрдХрдЕрдк рдкреАрдврд╝реА рдХреЗ рд▓рд┐рдП рд╢рд╛рд╕реНрддреНрд░реАрдп рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛, рд╕рдм рдХреБрдЫ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдбрд╛рдпрдирд╛рдорд┐рдХ рд░реВрдк рд╕реЗ ajax рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдФрд░ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВ? рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдорд╛рд░реНрдХрдЕрдк рдореЗрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рдмреЗрд╢рдХ, рдЖрдк рдЕрдкрдиреА рдЬрд╝рд░реВрд░рдд рдХреА рд╣рд░ рдЪреАрдЬрд╝ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдРрд╕рд╛ рд▓рдЧреЗрдЧрд╛ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рд╕реБрд▓рдЭ рдЧрдИ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдБ рдХреЛрдб рдбреБрдкреНрд▓реАрдХреЗрд╢рди рдХреА рд╕рдорд╕реНрдпрд╛ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рд╣реА рдбреЗрдЯрд╛ рдХреЛ рджреЛ рдмрд╛рд░ - рд╕рд░реНрд╡рд░ рдкрд░ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рд╡рд░реНрдгрд┐рдд рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ, рдЬреЛ рдЖрдЧреЗ рдЪрд▓рдХрд░ рдЕрдиреНрдп рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдбрд╛рдпрдиреЗрдорд┐рдХ рдорд╛рд░реНрдХрдЕрдк рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдкреНрд░рд╢реНрди рдХреНрд▓рд╛рдЗрдВрдЯ рдкрдХреНрд╖ рдкрд░ рдореЙрдбрд▓ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдФрд░ рдбреЗрдЯрд╛ рд╕рддреНрдпрд╛рдкрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╣реИред рдЗрд╕ рдкрд░ рдмрд╛рдж рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреАред
рдЗрд╕рд▓рд┐рдП, рдЧреНрд░рд╛рд╣рдХ рдкрдХреНрд╖ рдФрд░ рд╡рд┐рдиреАрдд рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП MVC рдореЙрдбрд▓ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред
рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░:
- рд╣рдо http рд╣реЗрдбрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдбрд┐рд▓реАрд╡рд░ рдХрд░реЗрдВрдЧреЗ
- рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛
- рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдмреЗрд╕ 64 рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЛ рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХрд░реЗрдВрдЧреЗ (рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ http рд╣реИрдбрд░ рдПрдПрд╕рд╕реАрдЖрдИрдЖрдИ рдореЗрдВ рдкрд╛рд░рд┐рдд рд╣реЛ рдЧрдпрд╛ рд╣реИ)ред
- рдмреИрдХрдмреЛрди рдореЙрдбрд▓ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдкрд╛рд░реНрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░реЗрдВ - рдЗрд╕рдореЗрдВ рд╣рдо рдЯреНрд░рд╛рдВрд╕рдорд┐рдЯреЗрдб рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдмреЗрд╕ 64 рд╕реЗ рдбрд┐рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВрдЧреЗред
- рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░, рдЖрдкрдХреЛ рдмреИрдХрдмреЛрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдмреИрдХрдмреЛрди-рд╡реЗрд▓рд┐рдбреЗрд╢рди.рдЬреЗрдПрд╕ - рд╕рддреНрдпрд╛рдкрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
Http рд╣реИрдбрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░
рдЗрд╕ рд▓реЗрдЦ рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЖрдк
рдпрд╣рд╛рдБ рд░реАрдврд╝-рд╕рддреНрдпрд╛рдкрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВред рдкреБрд╕реНрддрдХрд╛рд▓рдпред
рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб
рд╣рдо рд╕рд░реНрд╡рд░ рдкрд░ 2 рдлрд┐рд▓реНрдЯрд░ рд▓рд┐рдЦреЗрдВрдЧреЗ:
- рд╣реЗрдбрд░ рдореЗрдВ рдореЙрдбрд▓ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рд┐рд▓реНрдЯрд░
- рд╣реЗрдбрд░ рдореЗрдВ рдореЙрдбрд▓ рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдореЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рд┐рд▓реНрдЯрд░
рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдлрд╝рд┐рд▓реНрдЯрд░ (рдлрд╝реАрд▓реНрдб рдирд╛рдо, рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░, рдЖрджрд┐)public class MetaToHeader : ActionFilterAttribute { private readonly string header; public MetaToHeader(string header) { this.header = header; } public override void OnActionExecuted(ActionExecutedContext filterContext) { var result = filterContext.Result as JsonResult; if (result != null && result.Data != null) { var meta = GetMeta(result.Data); var jsonMeta = new JavaScriptSerializer().Serialize(meta); var jsonMetaBytes = Encoding.UTF8.GetBytes(jsonMeta); filterContext.HttpContext.Response.Headers.Add(header, Convert.ToBase64String(jsonMetaBytes)); } base.OnActionExecuted(filterContext); } private static IDictionary<string, object> GetMeta(object model) { var meta = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()); return meta.Properties.ToDictionary( p => p.PropertyName, p => new { label = p.GetDisplayName(), title = p.Description, placeholder = p.Watermark, readOnly = p.IsReadOnly } as object); } }
рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдо рдлрд╝рд┐рд▓реНрдЯрд░ public class ValidationToHeader : ActionFilterAttribute { private readonly string header; private static readonly Dictionary<string, Func<ModelClientValidationRule, List<object>>> Rules; public ValidationToHeader(string header) { this.header = header; } static ValidationToHeader() { Rules = new Dictionary<string, Func<ModelClientValidationRule, List<object>>>() { { "length", r => { var result = new List<object>(); if (r.ValidationParameters.ContainsKey("max")) result.Add(new {maxLength = r.ValidationParameters["max"]}); if (r.ValidationParameters.ContainsKey("min")) result.Add(new {minLength = r.ValidationParameters["min"]}); result.Add(new { msg = r.ErrorMessage }); return result; } }, { "range", r => { var result = new List<object>(); if (r.ValidationParameters.ContainsKey("max")) result.Add(new {max = r.ValidationParameters["max"]}); if (r.ValidationParameters.ContainsKey("min")) result.Add(new {min = r.ValidationParameters["min"]}); result.Add(new {msg = r.ErrorMessage}); return result; } }, { "remote", r => { var result = new Dictionary<string, object>(); if (r.ValidationParameters.ContainsKey("url")) result.Add("url", r.ValidationParameters["url"]); if (r.ValidationParameters.ContainsKey("type")) result.Add("type", r.ValidationParameters["type"]); result.Add("msg", r.ErrorMessage); return new List<object> { new {remote = result} }; } }, { "required", r => new List<object> { new { required = true, msg = r.ErrorMessage } } }, { "number", r => new List<object> { new { pattern = "number", msg = r.ErrorMessage } } } }; } public override void OnActionExecuted(ActionExecutedContext filterContext) { var result = filterContext.Result as JsonResult; if (result != null && result.Data != null) { var meta = GetRules(result.Data, filterContext.Controller.ControllerContext); var jsonMeta = new JavaScriptSerializer().Serialize(meta); var jsonMetaBytes = Encoding.UTF8.GetBytes(jsonMeta); filterContext.HttpContext.Response.Headers.Add(header, Convert.ToBase64String(jsonMetaBytes)); } base.OnActionExecuted(filterContext); } public static IDictionary<string, object> GetRules(object model, ControllerContext context) { var meta = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()); return meta.Properties.ToDictionary( p => p.PropertyName, p => PropertyRules(p, context) as object); } private static object[] PropertyRules(ModelMetadata meta, ControllerContext controllerContext) { return meta.GetValidators(controllerContext) .SelectMany(v => v.GetClientValidationRules()) .SelectMany(r => Rules[r.ValidationType](r)) .ToArray(); } }
рдпрд╣ рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдореЗрдВ рднреЗрдЬреЗ рдЧрдП рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде Json рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдЧреНрд░рд╛рд╣рдХ рднрд╛рдЧ
рдЧреНрд░рд╛рд╣рдХ рдкрд░, рдмрдирд╛рдПрдБ:
- рдореВрд▓ рд░реАрдврд╝ рдореЙрдбрд▓ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдкрд╛рд░реНрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ
- рдореВрд▓ рд░реАрдврд╝ рджреГрд╢реНрдп
рдЖрдзрд╛рд░ рдореЙрдбрд▓ (function () { var models = window.App.Models; models.DataMetaModel = Backbone.Model.extend({ metaHeader: 'data-meta', validationHeader: 'data-validation', urlRoot: '', initialize: function (options) { this.urlRoot = options.url; }, parse: function (response, xhr) { var metaData = xhr.xhr.getResponseHeader(this.metaHeader); var validationData = xhr.xhr.getResponseHeader(this.validationHeader); this.meta = metaData ? $.parseJSON(Base64.decode(metaData)) : undefined; this.validation = validationData ? $.parseJSON(Base64.decode(validationData)) : undefined; return response; } }); })();
рд╣рдо http рд╣реЗрдбрд░ рд╕реЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдФрд░ рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдореЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░реНрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рддрдм рдмреИрдХрдмреЛрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдмреИрдХрдмреЛрди-рд╡реЗрд▓рд┐рдбреЗрд╢рди рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред js
рдореВрд▓ рд░реАрдврд╝ рджреГрд╢реНрдп (function () { var views = window.App.Views; views.dataMetaView = Backbone.View.extend({ events: { 'submit': 'evSubmit', 'blur input[type=text]': 'evBlur', }, initialize: function (options) { _.extend(Backbone.Validation.callbacks, { valid: this.validCallback, invalid: this.invalidCallback, }); _.extend(Backbone.Validation.validators, { remote: this.remoteValidator }); Backbone.Validation.bind(this, { offFlatten: true
рдпрд╣рд╛рдВ рдмреИрдХрдмреЛрди рд╡реНрдпреВ рдореЗрдВ, рд╕рддреНрдпрд╛рдкрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА, рдмреИрдХрдмреЛрди-рд╡реИрд▓рд┐рдбреЗрд╢рди.рдЬреЗрдПрд╕ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рд╣реИ, рдЬреЛ рдкрд╣рд▓реА рдмрд╛рд░ рд╢реБрд░реВ рд╣реБрдЖ рд╣реИ:
Backbone.Validation.bind(this, { offFlatten: true
рджреВрд╕рд░реЗ, рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ (рд╡реИрдз, рдЕрдорд╛рдиреНрдп), рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд┐рдВрдЧ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ, рдЖрд░рдВрднрд┐рдХ рд╣реИрдВред рджреВрд░рд╕реНрде рд╕рддреНрдпрд╛рдкрди рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдпрд╣рд╛рдВ рднреА рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
remoteValidator: function (value, attr, customValue, model) { var result, data = model.toJSON(); data[attr] = value; $.ajax({ type: customValue.type || 'GET', data: data, url: customValue.url, async: false, success: function (state) { if (!state) result = customValue.msg || 'remote validation error'; }, error: function () { result = "remote validation error"; } }); return result; }
рдХреНрд▓рд╛рдЗрдВрдЯ рдкрдХреНрд╖ рдкрд░, рджреВрд░рд╕реНрде рд╕рддреНрдпрд╛рдкрди рд╡рд┐рд╢реЗрд╖рддрд╛ рд╕рд┐рд░реНрдл рдПрдХ рдЕрдЬрд╛рдХреНрд╕ рд╡рд┐рдзрд┐ рд╣реИ (рд╡рд┐рдзрд┐ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╕рд░реНрд╡рд░ рдкрдХреНрд╖ рдкрд░ рдореЙрдбрд▓ рдХреЗ рд╡рд┐рд╡рд░рдг рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ), рдЬреЛ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддрд╛ рд╣реИ рдЬреЛ рдорд╛рдиреНрдп рдХреНрд╖реЗрддреНрд░ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ:
- рд╕рдЪ - рдХреНрд╖реЗрддреНрд░ рд╡реИрдз рд╣реИ
- рдЧрд▓рдд - рдЕрдорд╛рдиреНрдп
рджреВрд░рд╕реНрде рд╕рддреНрдпрд╛рдкрди рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬрдм рд╕рддреНрдпрд╛рдкрди рдЕрд╕рдВрднрд╡ рд╣реИ рдпрд╛ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрдХреНрд╖ рдкрд░ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдХреЛрдб рдореЗрдВ, рджреВрд░рд╕реНрде рд╕рддреНрдпрд╛рдкрди рд╡рд┐рд╢реЗрд╖рддрд╛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╡рд░реНрдгрд┐рдд рд╣реИ
[Remote("RemoteEmailValidation", "Friends", ErrorMessage = " ")]
рдХреЗ рдЙрдкрдпреЛрдЧ
рд╕рд░реНрд╡рд░ рдХреА рдУрд░, рдЖрдкрдХреЛ рдПрдХ рд╡рд┐рдзрд┐ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдХрд┐ Json рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдбреЗрдЯрд╛ рднреЗрдЬ рджреЗрдЧреАред рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП рдмрдирд╛рдП рдЧрдП рдлрд╝рд┐рд▓реНрдЯрд░ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:
[MetaToHeader("data-meta")] [ValidationToHeader("data-validation")] public ActionResult GetData() { return Json(new Friend(), JsonRequestBehavior.AllowGet); }
Http рд╣реЗрдбрд░ рдХрд╛ рдирд╛рдо рдлрд┐рд▓реНрдЯрд░ рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдкрд╛рд░реНрд╕ рдкрджреНрдзрддрд┐ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рд╕рдорд╛рди рдирд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рдУрд░ рд╕реЗ,
CreateMMMelel рдмреИрдХрдмреЛрди рдмреЗрд╕ рдореЙрдбрд▓ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рдПрдХ
FriendModel Backbone рдореЙрдбрд▓ рдмрдирд╛рдПрдВ, рдЬрд┐рд╕рдореЗрдВ рдкрд╛рд░реНрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
(function() { var models = window.App.Models; models.FriendModel = models.DataMetaModel.extend({ initialize: function(options) { models.DataMetaModel.prototype.initialize.call(this, options); } }); })();
рд╣рдо рдПрдХ рдмреИрдХрдмреЛрди рд╡реНрдпреВ
рдиреНрдпреВрдлреНрд░реЗрдВрдб рднреА рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдмрдирд╛рдП рдЧрдП рдореВрд▓ рдмреИрдХрдмреЛрди рд╡реНрдпреВ
рдбреЗрдЯрд╛рдореИрдЯрд┐рд╡ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ:
(function () { var views = window.App.Views; views.NewFriend = views.dataMetaView.extend({ initialize: function (options) { views.dataMetaView.prototype.initialize.call(this); this.model.on('sync', this.render, this); this.template = _.template($(options.template).html()); }, render: function () { this.$el.html(this.template(this.model.toJSON())); views.dataMetaView.prototype.render.call(this); return this; }, load: function () { this.model.fetch(); } }); })();
рдпрд╣рд╛рдВ
рд░реЗрдВрдбрд░ рд╡рд┐рдзрд┐ рдореЗрдВ, рд╕рднреА рдЪрд░рдгреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдЖрдзрд╛рд░ рд░реЗрдВрдбрд░ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛
views.dataMetaView.prototype.render.call(this);
рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рдореЙрдбрд▓ рдХреЗ рд╡рд┐рд╡рд░рдг рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдлрд╝реАрд▓реНрдб рдореЗрдВ рдореЗрдЯрд╛рдбреЗрдЯрд╛ (рдирд╛рдо, рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░, рдЖрджрд┐) рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдПред рд╣рд╛рд▓рд╛рдБрдХрд┐, DOM рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рджрд┐рдП рдЧрдП рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдо рдирд╣реАрдВ рдЬреЛрдбрд╝реЗ рдЧрдП рд╣реИрдВред рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рд░реАрдврд╝ рдХреА рд╣рдбреНрдбреА рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкреБрд╕реНрддрдХрд╛рд▓рдпред
рдЙрджрд╛рд╣рд░рдг
рдПрдХ
рдорд┐рддреНрд░ рдореЙрдбрд▓ рдмрдирд╛рдПрдБ:
public class Friend { public int Id { get; set; } [Display(Name = "", Prompt = " ", Description = " ")] [Required(ErrorMessage = "First name required")] [StringLength(50, MinimumLength = 2)] public string FirstName { get; set; } [Display(Name = "", Prompt = " ", Description = " ")] [Required(ErrorMessage = "Last name required")] [StringLength(50, MinimumLength = 2)] public string LastName { get; set; } [Display(Name = "", Prompt = " ", Description = " ")] [Required(ErrorMessage = "Age required")] [Range(0, 120, ErrorMessage = "Age must be between 0 and 120")] public int? Age { get; set; } [Display(Name = " ", Prompt = " ", Description = " ")] [Required(ErrorMessage = "Email required")] [Email(ErrorMessage = "Not a valid email")] [Remote("RemoteEmailValidation", "Friends", ErrorMessage = " ")] public string Email { get; set; } }
рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ, рд╣рдо рдЙрд╕ рдореЙрдбрд▓ рдореЗрдВ рджреЛ рдлрд┐рд▓реНрдЯрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬреЛ рдореЙрдбрд▓ рд▓реМрдЯрд╛рддрд╛ рд╣реИ:
[MetaToHeader("data-meta")] [ValidationToHeader("data-validation")] public ActionResult GetData() { return Json(new Friend(), JsonRequestBehavior.AllowGet); }
рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░,
рдЙрдкрдпреЛрдЧ рдХреНрд▓реЙрдЬ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдореЙрдбрд▓ рдФрд░ рджреГрд╢реНрдп рдмрдирд╛рдПрдВ, рдФрд░ рдЙрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рднреА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ рдЬрд┐рд╕реЗ рд╡реНрдпреВ рдбрд╛рдпрдиреЗрдорд┐рдХ рдорд╛рд░реНрдХ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛:
<script type='text/template' id='dataMeta-template'> <form action="/Friends/Create" method="post"> <div class="control-group"> <label for="FirstName"></label> <div class="controls"> <input type='text' name="FirstName" value='<%- FirstName %>' /> </div> </div> <div class="control-group"> <label for="LastName"></label> <div class="controls"> <input type='text' name="LastName" value='<%- LastName %>' /> </div> </div> <div class="control-group"> <label for="Age"></label> <div class="controls"> <input type='text' name="Age" value='<%- Age %>' /> </div> </div> <div class="control-group"> <label for="Email"></label> <div class="controls"> <input type='text' name="Email" value='<%- Email %>' /> </div> </div> <p><button class="btn" type="submit">Create</button></p> </form> </script>
рдкреГрд╖реНрда рдкрд░ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ:
<script> (function($) { var models = window.App.Models, views = window.App.Views; var dataMetaModel = new models.FriendModel({ urlRoot: '/Friends/GetData' }); var dataMetaView = new views.NewFriend({ el: '#dataMeta', model: dataMetaModel, template: '#dataMeta-template' }); dataMetaView.load(); })(jQuery); </script>
рдкрд░рд┐рдгрд╛рдо



