Welcome to the Edument CQRS and Intentful Testing Starter Kit project page. On this page, you will find links to our open sourced CQRS Starter Kit on GitHub as well as tutorials to get you started.
تا پیش از دات نت 7، اگر درخواستی با یک بدنهی خالی، یعنی با مشخصات Content-Length == 0 به سمت یک اکشن متد که آنرا از طریق [FromBody] دریافت میکند، ارسال شود، با پیام خطای «A non-empty request body is required» خاتمه خواهد یافت. یک روش رفع سراسری آن، تنظیم زیر است:
var builder = WebApplication.CreateBuilder(args); builder.Services.Configure<MvcOptions>(options => { options.AllowEmptyInputInBodyModelBinding = true; });
public IActionResult Post([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] MyBody? body) { // body will be null if the request Content-Length == 0 }
public class ExampleController : Controller { public IActionResult Post(MyBody? body) // Nullable { // body will be null if the request Content-Length == 0 } public IActionResult Post(MyBody body) // Non-nullable { // Request will fail with a 400 and "A non-empty request body is required." // when Content-Length == 0 } }
ویدیوهای NET Conf 2022.
سه مطلب کوتاه
مشکل فایرفاکس با سایتهای msdn و codeplex
هر از چند گاهی در بلاگهای msdn و یا سایت codeplex با خطای زیر از طرف سایت مواجه میشوم:
Bad Request - Request Too Long
HTTP Error 400. The size of the request headers is too long.
اگر با این مشکل مواجه شدید، تمامی کوکیهای مربوط به سایتهای مذکور را یافته و حذف کنید.
به نظر باگی در فایرفاکس در این زمینه سبب میشود که کوکیهای تمام زیر سایتهای فوق با هم ترکیب شده و رشتهای بسیار طولانی بجای کوکی اصلی آن زیر سایت به هاست ارسال شود.
که البته عکس العمل سایتهای مایکروسافت از دیدگاه امنیتی هم جالب توجه است (برای برنامه نویسهای وب).
IE8 و ارائهی fakepath بجای آدرس فایل
کنترل استاندارد آپلود فایل در مرورگرهای جدید، دیگر آدرس محلی فایل را حتی در اختیار اسکریپتهای سمت کاربر نیز قرار نمیدهند. فایرفاکس مدت زیادی است که این مورد را پیاده سازی کرده. اما IE بجای اینکه یک رشتهی خالی را بازگشت دهد مسیر c:\fakepath را ارائه خواهد داد (fakepath جزو استاندارد html 5 است). اگر احیانا با این مورد برخورد داشتید، با استفاده از تنظیم زیر میتوان مانند سابق مسیر کامل را نیز دریافت کرد:
Internet Explorer -> Tools -> Internet Option -> Security -> Custom ->
find the "Include local directory path when uploading files to a server"
-> click on "Enable"
اهمیت این مورد هم برای من این است که IE، یعنی همان مرورگر کاری در اکثر شرکتها (و این مورد فوق را به سادگی از طریق گروپ پالیسی میتوان به تمام کامپیوترها اعمال کرد).
علت تایم آوت و باز نشدن یک سری از سایتها در ایران
مدت زیادی این سؤال برای من وجود داشت که وجه مشترک سایتهایی مانند dotnetkicks.com ، summerofnhibernate.com ، lessthandot.com و امثال آن چیست که از این طرف باز نمیشوند؟
اگر به آدرسهای فوق که به سایت domaintools.com ختم میشوند، مراجعه کنید و سپس برگهی Server Stats آنها را ملاحظه نمائید، همگی توسط Godaddy.com Inc هاست میشوند. این شرکت غیرمحترم، IP های ایرانی را بسته است (مطلب جدیدی هم نیست).
var client = new SoapDisposableEmailAddressDetectorClient(); var context = new soapContext { //todo: get your API key here: http://www.nameapi.org/en/register/ apiKey = "test" }; var result = client.isDisposable(context, "DaDiDoo@mailinator.com"); if (result.disposable.ToString() == "YES") { Console.WriteLine("YES! It's Disposable!"); }
Additional information: The remote server returned an unexpected response: (400) Bad Request.
<html><head><title>Bad Request</title></head><body><h1>Bad Request</h1><p>No api-key provided!</p></body></html>
اگر همین وب سرویس را توسط امکانات سایت http://wsdlbrowser.com بررسی کنید، بدون مشکل کار میکند. اما تفاوت در کجاست؟
خروجی ارسالی به سرور، توسط سایت http://wsdlbrowser.com به این شکل است:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://disposableemailaddressdetector.email.services.v4_0.soap.server.nameapi.org/"> <SOAP-ENV:Body> <ns1:isDisposable> <context> <apiKey>test</apiKey> </context> <emailAddress>sdsdg@site.com</emailAddress> </ns1:isDisposable> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <isDisposable xmlns="http://disposableemailaddressdetector.email.services.v4_0.soap.server.nameapi.org/"> <context xmlns=""><apiKey>test</apiKey></context> <emailAddress xmlns="">DaDiDoo@mailinator.com</emailAddress> </isDisposable> </s:Body> </s:Envelope>
برای این منظور به سه کلاس ذیل خواهیم رسید:
public class EndpointBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new ClientMessageInspector()); } } public class ClientMessageInspector : IClientMessageInspector { public void AfterReceiveReply(ref Message reply, object correlationState) { } public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel) { request = new MyCustomMessage(request); return request; } } /// <summary> /// To customize WCF envelope and namespace prefix /// </summary> public class MyCustomMessage : Message { private readonly Message _message; public MyCustomMessage(Message message) { _message = message; } public override MessageHeaders Headers { get { return _message.Headers; } } public override MessageProperties Properties { get { return _message.Properties; } } public override MessageVersion Version { get { return _message.Version; } } protected override void OnWriteStartBody(XmlDictionaryWriter writer) { writer.WriteStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/"); } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { _message.WriteBodyContents(writer); } protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer) { writer.WriteStartElement("SOAP-ENV", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/"); writer.WriteAttributeString("xmlns", "ns1", null, value: "http://disposableemailaddressdetector.email.services.v4_0.soap.server.nameapi.org/"); } }
var client = new SoapDisposableEmailAddressDetectorClient(); client.Endpoint.Behaviors.Add(new EndpointBehavior());
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید.
Asp.Net Identity #3
using System.Web; using System.Web.Mvc; using Microsoft.AspNet.Identity.Owin; using Users.Infrastructure; namespace Users.Controllers { public class HomeController : Controller { private AppUserManager UserManager { get { return HttpContext.GetOwinContext().GetUserManager<AppUserManager>(); } } // GET: Home public ActionResult Index() { return View(UserManager.Users); } }
@using Users.Models @model IEnumerable<AppUser> @{ ViewBag.Title = "Index"; } <div class="panel panel-primary"> <div class="panel-heading"> User Accounts </div> <table class="table table-striped"> <tr><th>ID</th><th>Name</th><th>Email</th></tr> @if (!Model.Any()) { <tr><td colspan="3" class="text-center">No User Accounts</td></tr> } else { foreach (AppUser user in Model) { <tr> <td>@user.Id</td> <td>@user.UserName</td> <td>@user.Email</td> </tr> } } </table> </div> @Html.ActionLink("Create", "CreateUser", null, new { @class = "btn btn-primary" })
نحوهی ساخت یک کاربر جدید
namespace Users.Models { public class CreateModel { [Required] public string Name { get; set; } [Required] public string Email { get; set; } [Required] public string Password { get; set; } } }
public ActionResult CreateUser() { return View(); } [HttpPost] public async Task<ActionResult> CreateUser(CreateModel model) { if (!ModelState.IsValid) return View(model); var user = new AppUser { UserName = model.Name, Email = model.Email }; var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { return RedirectToAction("Index"); } foreach (var error in result.Errors) { ModelState.AddModelError("", error); } return View(model); }
@model Users.ViewModels.CreateModel @Html.ValidationSummary(false) @using (Html.BeginForm()) { <div class="form-group"> <label>Name</label> @Html.TextBoxFor(x => x.UserName, new { @class = "form-control" }) </div> <div class="form-group"> <label>Email</label> @Html.TextBoxFor(x => x.Email, new { @class = "form-control" }) </div> <div class="form-group"> <label>Password</label> @Html.PasswordFor(x => x.Password, new { @class = "form-control" }) </div> <button type="submit" class="btn btn-primary">Create</button> @Html.ActionLink("Cancel", "Index", null, new { @class = "btn btn-default" }) }
اعتبار سنجی رمز
var manager = new AppUserManager(new UserStore<AppUser>(db)) { PasswordValidator = new PasswordValidator { RequiredLength = 6, RequireNonLetterOrDigit = false, RequireDigit = false, RequireLowercase = true, RequireUppercase = true } };
فقط دوستان توجه داشته باشید که کد بالا را در متد Create از کلاس AppUserManager استفاده کنید.
اعتبار سنجی نام کاربری
برای اعبارسنجی نام کاربری از کلاس UserValidator به صورت زیر استفاده میکنیم:
manager.UserValidator = new UserValidator<AppUser>(manager) { AllowOnlyAlphanumericUserNames = true, RequireUniqueEmail = true };
کد بالا را نیز در متد Create از کلاس AppUserManager قرار میدهیم.
$('#dbcat').change(function () { var selectedItem = $(this).val(); $.post( "-----url----", { item: selectedItem } ); });
نمایش خروجی RSS سایتهای دیگر به کمک jQuery
کتابخانه Hangfire
An easy way to perform background job processing in your .NET and .NET Core applications. No Windows Service or separate process required. CPU and I/O intensive, long-running and short-running jobs are supported. Backed by Redis, SQL Server, SQL Azure and MSMQ.
PM> Install-Package Hangfire
After installation, update your existing OWIN Startup file with the following lines of code. If you do not have this class in your project or don't know what is it, please read the Quick start guide to learn about how to install Hangfire.
public void Configuration(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("<connection string or its name>");
app.UseHangfireServer();
app.UseHangfireDashboard();
}