http://localhost:2215/Account/LogOn?ReturnUrl=%2fScripts%2fjquery-1.7.1.js
<authorization> <deny users="?" /> </authorization>
http://localhost:2215/Account/LogOn?ReturnUrl=%2fScripts%2fjquery-1.7.1.js
<authorization> <deny users="?" /> </authorization>
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> <link href="~/Content/PersianDatePicker.css" rel="stylesheet" /> </head> <body> @RenderBody() <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script src="~/Scripts/PersianDatePicker.js"></script> @RenderSection("Scripts", required: false) </body> </html>
@using System.Globalization @model DateTime? @{ Func<DateTime, string> toPersianDate = date => { var dateTime = new DateTime(date.Year, date.Month, date.Day, new GregorianCalendar()); var persianCalendar = new PersianCalendar(); return persianCalendar.GetYear(dateTime) + "/" + persianCalendar.GetMonth(dateTime).ToString("00") + "/" + persianCalendar.GetDayOfMonth(dateTime).ToString("00"); }; var today = toPersianDate(DateTime.Now); var name = this.ViewContext.ViewData.ModelMetadata.PropertyName; var value = Model.HasValue ? toPersianDate(Model.Value) : string.Empty; } <input type="text" dir="ltr" name="@name" id="@name" value="@value" onclick="PersianDatePicker.Show(this,'@today');" />
// Location: Views\Shared\EditorTemplates\PersianDatePicker.cshtml [UIHint("PersianDatePicker")] public DateTime AddDate { set; get; }
<div> <label>تاریخ:</label> @Html.EditorFor(model => model.AddDate) </div>
Content-Security-Policy: script-src 'self' X-WebKit-CSP: script-src 'self' X-Content-Security-Policy: script-src 'self'
Content-Security-Policy: script-src 'self' https://youcdn.com X-WebKit-CSP: script-src 'self' https://yourcdn.com X-Content-Security-Policy: script-src 'self' https://yourcdn.com
Content-Security-Policy: default-src 'self' https://youcdn.com X-WebKit-CSP: default-src 'self' https://yourcdn.com X-Content-Security-Policy: default-src 'self' https://yourcdn.com
using System; using System.Web; namespace AntiXssHeaders { public class SecurityHeadersConstants { public static readonly string XXssProtectionHeader = "X-XSS-Protection"; public static readonly string XFrameOptionsHeader = "X-Frame-Options"; public static readonly string XWebKitCspHeader = "X-WebKit-CSP"; public static readonly string XContentSecurityPolicyHeader = "X-Content-Security-Policy"; public static readonly string ContentSecurityPolicyHeader = "Content-Security-Policy"; public static readonly string XContentTypeOptionsHeader = "X-Content-Type-Options"; } public class ContentSecurityPolicyModule : IHttpModule { public void Dispose() { } public void Init(HttpApplication app) { app.BeginRequest += AppBeginRequest; } void AppBeginRequest(object sender, EventArgs e) { var app = (HttpApplication)sender; var response = app.Context.Response; setHeaders(response); } private static void setHeaders(HttpResponse response) { response.Headers.Set(SecurityHeadersConstants.XFrameOptionsHeader, "SameOrigin"); // For IE 8+ response.Headers.Set(SecurityHeadersConstants.XXssProtectionHeader, "1; mode=block"); response.Headers.Set(SecurityHeadersConstants.XContentTypeOptionsHeader, "nosniff"); //todo: Add /Home/Report --> public JsonResult Report() { return Json(true); } const string cspValue = "default-src 'self';"; // For Chrome 16+ response.Headers.Set(SecurityHeadersConstants.XWebKitCspHeader, cspValue); // For Firefox 4+ response.Headers.Set(SecurityHeadersConstants.XContentSecurityPolicyHeader, cspValue); response.Headers.Set(SecurityHeadersConstants.ContentSecurityPolicyHeader, cspValue); } } }
//// RegisterGlobalFilters -> filters.Add(new ContentSecurityPolicyFilterAttribute()); public class ContentSecurityPolicyFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var response = filterContext.HttpContext.Response; response.AddHeader("Content-Security-Policy", "script-src 'self'"); // the rest ... base.OnActionExecuting(filterContext); } }
sn -i key.pfx VS_KEY_2B6952079A0469C6
using System;
public class SampleModel
{
public DateTime StartDate { get; set; }
public string Data { get; set; }
public int Id { get; set; }
}
using System; using System.ComponentModel.DataAnnotations; public class SampleModel { [Required(ErrorMessage = "Start date is required")] public DateTime StartDate { get; set; } [Required(ErrorMessage = "Data is required")] public string Data { get; set; } public int Id { get; set; } }
@model SampleModel @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <section> <header> <h3>SampleModel</h3> </header> @Html.ValidationSummary(true, null, new { @class = "alert alert-error alert-block" }) @using (Html.BeginForm("SaveData", "Sample", FormMethod.Post)) { <p> @Html.LabelFor(x => x.StartDate) @Html.TextBoxFor(x => x.StartDate) @Html.ValidationMessageFor(x => x.StartDate) </p> <p> @Html.LabelFor(x => x.Data) @Html.TextBoxFor(x => x.Data) @Html.ValidationMessageFor(x => x.Data) </p> <input type="submit" value="Save"/> } </section>
public class SampleController : Controller { // // GET: /Sample/ public ActionResult Index() { return View(); } public ActionResult SaveData(SampleModel item) { if (ModelState.IsValid) { //save data } else { ModelState.AddModelError("","لطفا خطاهای زیر را برطرف نمایید"); RedirectToAction("Index", item); } return View("Index"); } }
تا اینجای کار روال عادی همیشگی است. اما برای طراحی Attribute دلخواه جهت اعتبار سنجی (مثلا برای مجبور کردن کاربر به وارد کردن یک فیلد با پیام دلخواه و زبان دلخواه) باید یک کلاس جدید تعریف کرده و از کلاس RequiredAttribute ارث ببرد. در پارامتر ورودی این کلاس جهت کار با Resourceهای ثابت در نظر گرفته شده است اما برای اینکه فیلد دلخواه را از دیتابیس بخواند این روش جوابگو نیست. برای انجام آن باید کلاس RequiredAttribute بازنویسی شود.
کلاس طراحی شده باید به صورت زیر باشد:
public class VegaRequiredAttribute : RequiredAttribute, IClientValidatable { #region Fields (2) private readonly string _resourceId; private String _resourceString = String.Empty; #endregion Fields #region Constructors (1) public VegaRequiredAttribute(string resourceId) { _resourceId = resourceId; ErrorMessage = _resourceId; AllowEmptyStrings = true; } #endregion Constructors #region Properties (1) public new String ErrorMessage { get { return _resourceString; } set { _resourceString = GetMessageFromResource(value); } } #endregion Properties #region Methods (2) // Public Methods (1) public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { yield return new ModelClientValidationRule { ErrorMessage = GetMessageFromResource(_resourceId), ValidationType = "required" }; } // Private Methods (1) private string GetMessageFromResource(string resourceId) { var errorMessage = HttpContext.GetGlobalResourceObject(_resourceId, "Yes") as string; return errorMessage ?? ErrorMessage; } #endregion Methods }
HttpContext.GetGlobalResourceObject(_resourceId, "Yes") as string;
که عنوان کلید Resource را از سازنده کلاس گرفته (کد اقای یوسف نژاد) رشته معادل آن را از دیتابیس بازیابی میکند.
2- ارث بری از اینترفیس IClientValidatable، در صورتی که از این اینترفیس ارث بری نداشته باشیم. Validator طراحی شده در طرف کلاینت کار نمیکند. بلکه کاربر با کلیک بروی دکمه مورد نظر دادهها را به سمت سرور ارسال میکند. در صورت وجود خطا در پست بک خطا نمایش داده خواهد شد. اما با ارث بری از این اینترفیس و پیاده سازی متد GetClientValidationRules میتوان تعریف کرد که در طرف کلاینت با استفاده از Unobtrusive jQuery پیام خطای مورد نظر به کنترل ورودی مورد نظر (مانند تکست باکس) اعمال میشود. مثلا در این مثال خصوصیت data-val-required به input هایی که قبلا در مدل ما Reqired تعریف شده اند اعمال میشود.
حال در مدل تعریف شده میتوان به جای Required میتوان از VegaRequiredAttribute مانند زیر استفاده کرد. (همراه با نام کلید مورد نظر در دیتابیس)
public class SampleModel { [VegaRequired("RequiredMessage")] public DateTime StartDate { get; set; } [VegaRequired("RequiredMessage")] public string Data { get; set; } public int Id { get; set; } }
جهت فعال ساری اعتبار سنجی سمت کلاینت ابتدا باید اسکریپتهای زیر به صفحه اضافه شود.
<script src="@Url.Content("~/Scripts/jquery-1.9.1.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<appSettings> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true"/> </appSettings>
<script type="text/javascript"> jQuery.validator.addMethod('required', function (value, element, params) { if (value == null | value == "") { return false; } else { return true; } }, ''); jQuery.validator.unobtrusive.adapters.add('required', {}, function (options) { options.rules['required'] = true; options.messages['required'] = options.message; }); </script>
<script src="js/kendo.all.min.js" type="text/javascript"></script>