@if (!await this.TrySectionAsync("NodeHeaderSection")) { if (IsSectionDefined("NodeHeaderContentSection")) {
@await RenderSectionAsync("NodeHeaderContentSection")
} } @using Microsoft.AspNetCore.Authorization; @inject IAuthorizationService auth @if (auth.AuthorizeAsync(User, "MEDIA_USERS").Result.Succeeded) {
  • Управление
  • } var useSSO = (bool)(ViewData.Eval("useSSO") ?? false); /* * Body Length Limit */ [RequestSizeLimit(100_000_000)] [DisableRequestSizeLimit, RequestFormLimits(MultipartBodyLengthLimit = int.MaxValue, ValueLengthLimit = int.MaxValue)] public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.Configure(options => { options.MultipartBodyLengthLimit = 134217728; // Set the limit to 128 MB }); } services.Configure(x => { x.ValueLengthLimit = int.MaxValue; x.MultipartBodyLengthLimit = int.MaxValue; // if don't set default value is: 128 MB x.MultipartHeadersLengthLimit = int.MaxValue; }); public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() .UseKestrel(options => { options.Limits.MaxRequestBodySize = 134217728; }); services.Configure(options => { options.Limits.MaxRequestBodySize = int.MaxValue; // if don't set default value is: 30 MB }); app.UseIIS(options => { options.MaxRequestBodySize = 1048576000; }); services.Configure(options => { options.MaxRequestBodySize = int.MaxValue; }); app.MapGet("/debug/routes", (IEnumerable endpointSources) => string.Join("\n", endpointSources.SelectMany(source => source.Endpoints))); if (data2 == null) { throw SuppExceptions.Http404_NotFound(); } return new HttpException(_Constants.HTTP_403, _Resources.Exceptions.Http_403_Forbidden); Transient — при каждом обращении создается новый экземпляр (объект на обращение) Transient: при каждом обращении к сервису создается новый объект сервиса. В течение одного запроса может быть несколько обращений к сервису и при каждом обращении будет создаваться новый объект. Подобная модель жизненного цикла наиболее подходит для легковесных сервисов, которые не хранят данных о состоянии Scoped — при обращении в рамках одного запроса (объект на запрос) Scoped: для каждого запроса создается свой объект сервиса. Если в течение одного запроса есть несколько обращений к одному сервису, то при всех этих обращениях будет использоваться один и тот же объект сервиса. Singleton — при каждом обращении используется один и тот же экземпляр (объект на приложение) Singleton: объект сервиса создается при первом обращении к нему, все последующие запросы используют один и тот же ранее созданный объект сервиса [.csproj] net6.0 disable enable ru-RU,en-US true false false true $(NoWarn);1591 0.0.0 $(Version) Roman Koff $(Authors) true PreserveNewest PreserveNewest PreserveNewest @(Context.Request.Scheme)://@(Context.Request.Host)@Url.Content("~/") ViewData["IpAddress"] = HttpContext.Connection.RemoteIpAddress?.ToString(); JSON: public static JsonSerializerOptions DefaultJsonSerializerOptions => new() { // DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true }; CORS: builder.Services.AddCors(o => o.AddPolicy("AllowAll", p => p.WithOrigins("*"))); app.UseCors("AllowAll"); RazorRuntimeCompilation: public void ConfigureServices( IServiceCollection services) { services } builder.Services .AddRazorPages() .AddRazorRuntimeCompilation(); builder.Services .AddControllersWithViews() .AddRazorRuntimeCompilation(); builder.Services .AddSwaggerGen(o => { o.EnableAnnotations(); o.IncludeXmlComments( Path.Combine( AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml")); }); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); builder.Services.AddDbContext(o => { o.UseNpgsql(builder.Configuration.GetConnectionString("SberDbContext")); }); app.SberDbCreateIfNotExists(app.Environment.IsDevelopment()); @if (Current.HttpContext.Connection.RemoteIpAddress.ToString() == "10.52.210.49") { } @{ var hostName = System.Net.Dns.GetHostName(); @hostName
    var ips = await System.Net.Dns.GetHostAddressesAsync(hostName); foreach (var _ in ips) { @_
    } } dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}"); Console.WriteLine(d.number); Console.WriteLine(d.str); Console.WriteLine(d.array.Count); @functions { private class Dto { public string Data { get;set; } } } @{ Func petTemplate = @

    You have a pet named @item.Name.

    ; var pets = new object[] { new { Name = "Rin Tin Tin" }, new { Name = "Mr. Bigglesworth" }, new { Name = "K-9" } }; } @foreach (var pet in pets) { @petTemplate(pet) } @{ class ListPackage { public string[] ListItems { get; set; } public string Style { get; set; } } Func template = @
      @foreach (var listItem in item.ListItems) {
    • @listItem
    • }
    ; } @template(new ListPackage { ListItems = new[] { "A","B","C" }, Style = "pretty" }) @{ void Template(string[] listItems, string style) {
      foreach (var listItem in listItems) {
    • @listItem
    • }
    } } @{ Template(new[] { "A","B","C" }, "pretty" ); } [HttpGet] [Route("get-edustandards")] public virtual IActionResult GetEdustandards() { var model = from level1 in _context.Levels .Include(x => x.Slave_Directions) .ThenInclude(x => x.Slave_Standards) where !level1.IsDisabled orderby level1.Group select new { level1.Group, level1.Title, Directions = from direction1 in level1.Slave_Directions where !direction1.IsDisabledEdu orderby direction1.Code select new { direction1.Code, direction1.Title, Standards = from standard1 in direction1.Slave_Standards where !standard1.IsDisabledStandard orderby standard1.Year select new { standard1.Title, standard1.Url, standard1.Year } } }; if (model == null) return NotFound(); return Ok(model); } public IActionResult JsonTest() { return Json(new { Foo = 1, Goo = true, Koo = "Test" }); } https://edi.wang/post/2018/10/31/migrating-old-aspnet-applications-to-net-core 6. Custom Http Headers In classic ASP.NET, you could add custom http headers to each response via Web.Config like this In .NET Core, if you need to host your application without Windows, you can’t use Web.config. So, you can do it via a third party NuGet package: NetEscapades.AspNetCore.SecurityHeaders app.UseSecurityHeaders(new HeaderPolicyCollection() .AddCustomHeader("X-UA-Compatible", "IE=edge") .AddCustomHeader("X-Developed-By", "Edi Wang") ); 7. Get Client IP Address and HttpContext In classic ASP.NET we used to get client IP Address by Request.UserHostAddress. But this does not apply to ASP.NET Core 2.x. We need a different way to retrieve HTTP Request information. Define a variable in your MVC controller private IHttpContextAccessor _accessor; DI into the controller's constructor public SomeController(IHttpContextAccessor accessor) { _accessor = accessor; } Retrive the IP Address _accessor.HttpContext.Connection.RemoteIpAddress.ToString() This is how it is done. If your ASP.NET Core project is created with the default MVC template, you should have the DI for HttpContextAcccessor in Startup.cs services.AddHttpContextAccessor(); services.TryAddSingleton(); The RemoteIpAddress is in type of IPAddress, not string. It contains IPv4, IPv6 and other information, it is not like the classic ASP.NET, which will be more useful to us. If you want to access this information in Razor Views (cshtml). Just use @inject to DI into the view: @inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor and then use it in your razor page: Client IP: @HttpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString() 12. Session and Cookie Session is not enabled by default in ASP.NET Core, you must manually add the Session support. services.AddDistributedMemoryCache(); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(20); options.Cookie.HttpOnly = true; }); and app.UseSession(); To get and set values: HttpContext.Session.SetString("CaptchaCode", result.CaptchaCode); HttpContext.Session.GetString("CaptchaCode"); To clear values: context.Session.Remove("CaptchaCode"); Check more at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-2.1 16. Anti-Forgery Token The anti-forgery token has a few improvements. First, you can customize cookie and field names now. services.AddAntiforgery(options => { options.Cookie.Name = "X-CSRF-TOKEN-MOONGLADE"; options.FormFieldName = "CSRF-TOKEN-MOONGLADE-FORM"; }); Second, you no longer need to manually add this code to every form. @Html.AntiForgeryToken() If you are using the new form tag helper, the anti-forgery field will be automatically added when your view is rendered to the client: But you will still need to add [ValidateAntiForgeryToken] attribute to the corresponding Action. However, there’s another way to Automatically validate anti-forgery tokens for every POST actions. services.AddMvc(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())); Or you can do this to a specific Controller. [Authorize] [AutoValidateAntiforgeryToken] public class ManageController : Controller 18. API Behavior Differences Some code from classic ASP.NET will compile without error, but it does not guarantee runtime success. For example, this code from ASP.NET in .NET Framework will throw exception in ASP.NET Core: var buffer = new byte[context.Request.Body.Length]; context.Request.Body.Read(buffer, 0, buffer.Length); var xml = Encoding.Default.GetString(buffer); It will result in System.NotSupportedException: Specified method is not supported. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.get_Length() And we need to use a different way to do it in .NET Core: var xml = await new StreamReader(context.Request.Body, Encoding.Default).ReadToEndAsync(); 19. Watch out for the GDPR problem ASP.NET Core 2.1 by default added the GDPR support, which can make some problems for us. You can check https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.1 for details. The major problem is that Cookie won’t work until user accepts the GDPR policy. You need to check what cookie is essential for your website to work even the user hasn’t accept the GDPR policy and set them to IsEssential. This is an example in my blog system: private void SetPostTrackingCookie(CookieNames cookieName, string id) { var options = new CookieOptions { Expires = DateTime.UtcNow.AddDays(1), SameSite = SameSiteMode.Strict, Secure = Request.IsHttps, // Mark as essential to pass GDPR // https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.1 IsEssential = true }; Response.Cookies.Append(cookieName.ToString(), id, options); } Another problem is if you are using Session, then you must make user accept GDPR policy, or it won’t work, because Session relies on Cookie to store the SessionID to client side.