Страницы

Поиск по вопросам

Показаны сообщения с ярлыком asp.net-core-mvc. Показать все сообщения
Показаны сообщения с ярлыком asp.net-core-mvc. Показать все сообщения

среда, 22 января 2020 г.

.net core mvc 6 (razor) не английские символы автоматом переводятся в Unicode Hex Character

#razor #net_core #aspnet_core_mvc


В .net core в представлениях (Razor) теперь все НЕ английские символы автоматически
конвертируются в соотвествующий хекс код. 

и теперь весь русский текст, который берётся из модели, или из переменных и пр. будут
выглядеть как: 

Мы не #x441;мо ...


И чтоб получить нормальный текст на русском нужно её значение выводить используя
Html.Raw()

тоесть если я в контроллере присвою переменной 

string txt="текст на русском";


и в представлении напишу

Смотрите это: @txt


то в html разметке я увижу:

смотрите это:  Мыне#x441;можем 


Если же использовать стандартные структуры типа 




то из модели весь текст с валидацией на русском автоматом преобразуется и получим  




конечно для конечного пользователя ничего не изменится и на страничке он видит правильный
русский текст, однако сам html заметно растет.

Как "обьяснить" .net core, что символы латинские "не опасны" и не нужно их заменять
при выводе вместе с символами "&<> и т.п. ?

В общем сделать так как было раньше...
    


Ответы

Ответ 1



в файле Startup.cs в public void ConfigureServices(IServiceCollection services) { .... //Чтобы кирилические символы не переводились в соответствующий Unicode Hex Character Code services.Configure(options => { options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All); }); }

среда, 25 декабря 2019 г.

Нестандартное (для меня) поведение параметров в контролере asp.net core

#c_sharp #aspnet_core #aspnet_core_mvc


Когда-то в Web Api 2 я мог написать такой action:

public class INP
{
    public string value { get; set; }
}
public string Post(INP con)
{
    return con.value;
}


и все отлично работало как с ContentType: application/x-www-form-urlencoded отправленным
от клиента, так и с ContentType: application/json.

Однако, в asp.net core все не так просто: с вышеприведенным кодом ContentType: application/x-www-form-urlencoded
работает, а вот ContentType: application/json оставляет мне просто null в коде. Если
обрамлять параметр атрибутом [FromBody], то ситуация меняется: с ContentType: application/json
все отлично, а вот с ContentType: application/x-www-form-urlencoded мне вовсе приходит
ответ вида 415 Unsupported Media Type.

Итак, сам вопрос: как в asp.net core написать action, который бы принимал мне параметр
разных ContentType'ов, как это было в Web Api 2? И почему поведение изменилось?
    


Ответы

Ответ 1



Этот вопрос можно решить таким путем: нужно создать две разные Action method-ы, которые смогут специфически байндить данные необходимые для отправки, а затем делегировать обработку вызовов к общему методу. Например: public class MyController : Controller { //для ContentType: application/x-www-form-urlencoded [HttpPost] public IActionResult Index(MyClass myclass){ return DoSomething(myclass); } //и для ContentType: application/json [HttpPost] public IActionResult IndexFromBody([FromBody] MyClass myclass){ return DoSomething(myclass); } private IActionResult DoSomething(MyClass myclass){ // сделай тут что нибудь с myclass // ... // ... return Json(myclass); } } Зачем Изменения? Разве раньше не было попроще? Может быть, но по мнению Дэмиана Эдвардса в сообществе Standup, основная причина это безопасность, в частности - предотвращение Межсайтовой подделки запросов (CSRF). UPDATE Вы должны решить эту проблему routing-ом, но если вы попытаетесь отобразить две вышеуказанные действия по одному и тому же маршруту, это приведет к ошибке. Решением этого будет создание пользовательского маршрута и вызов соответствующего метода по заголовку. Я понимаю что это требует больше усилий, чем этого стоит, но они говорят что эти изменения в целях безопасности, я не стал глубоко изучать как именно это предотвращает CSRF. Вы можете погуглить или же посмотреть тут.

среда, 17 июля 2019 г.

Razor Pages добавление и присвоение ролей

Я пытаюсь понять, как в Razor Pages 2.1. добавлять роли и присваивать их пользователям. Мне необходимо создать роль администратора и присвоить её предсозданному (seed) пользователю.
Я нашел, как это делается в MVC делается в MVC (вторая статья), но к сожалению, эти подход в Razor Pages у меня не сработали.
Подскажите, как можно создать и присвоить роли в Razor Pages 2.1.


Ответ

Получилось сделать следующим образом. Сперва, я воспользовался кодом, предложенным пользователем Paul Madson в https://stackoverflow.com/questions/42471866/how-to-create-roles-in-asp-net-core-and-assign-them-to-users. Нижеследующий метод я вставил в файл Startup.cs. Он создает роль администратора и присваивает её предсоздаваемому пользователю.
private void CreateRoles(IServiceProvider serviceProvider) { var roleManager = serviceProvider.GetRequiredService>(); var userManager = serviceProvider.GetRequiredService>(); Task roleResult; string email = "someone@somewhere.com";
//Check that there is an Administrator role and create if not Task hasAdminRole = roleManager.RoleExistsAsync("Administrator"); hasAdminRole.Wait();
if (!hasAdminRole.Result) { roleResult = roleManager.CreateAsync(new IdentityRole("Administrator")); roleResult.Wait(); }
//Check if the admin user exists and create it if not //Add to the Administrator role
Task testUser = userManager.FindByEmailAsync(email); testUser.Wait();
if (testUser.Result == null) { ApplicationUser administrator = new ApplicationUser { Email = email, UserName = email, Name = email };
Task newUser = userManager.CreateAsync(administrator, "_AStrongP@ssword!123"); newUser.Wait();
if (newUser.Result.Succeeded) { Task newUserRole = userManager.AddToRoleAsync(administrator, "Administrator"); newUserRole.Wait(); } }
}
Затем, в этом же файле в методе Configure я добавил аргумент IServiceProvider serviceProvider, то есть по части сигнатуры он стал выглядеть наподобие Configure(..., IServiceProvider serviceProvider). В нем же, в самом конце, я добавил строку CreateRoles(serviceProvider). Чтобы этот код работал, предварительно следует создать, например, в папке Data. следующий класс:
using Microsoft.AspNetCore.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks;
namespace Sobopedia.Data { public class ApplicationUser: IdentityUser { public string Name { get; set; } } }
Наконец, в методе ConfigureServices следует заменить
services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders();
на
services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders();
В результате, после запуска программы в таблице AspNetRoles у вас появится новая роль, а в таблице AspNetUsers новый пользователь, обладающий этой ролью.
К сожалению, если вы создавали шаблон с изначальной авторизацией, то при добавлении
services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders();
перестанут работать страницы Login и Registration. Чтобы исправить это, необходимо:
Scaffold Identity следуя (https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-2.1&tabs=visual-studio). Если вы используете шаблон с предсозданной авторизацией, то смотрите раздел Scaffold identity into a Razor project with authorization. После создания шаблона следует заменить во всем решении все IdentityUser на ApplicationUser. За исключением класса ApplicationUser, который по прежнему должен наследовать IdentityUser. Убрать из Areas/identity/Pages/Account/Register.cs (то есть модели) все, что связано с EmailSernder, если у вас нет его имплементации.
Чтобы проверить корректность работы данного решения можно сделать следующее. В конце метода ConfigureServices в классе Startup.cs добавляем следующее:
services.AddAuthorization(options => { options.AddPolicy("RequireAdministratorRole", policy => policy.RequireRole("Administrator")); });
services.AddMvc().AddRazorPagesOptions(options => { options.Conventions.AuthorizePage("/Contact","RequireAdministratorRole"); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
Также, для надежности или если этот код не сработает, в модель страницы Contact можно добавить [Authorize(Roles = "Administrator")], чтобы она выглядели следующим образом:
namespace Sobopedia.Pages { [Authorize(Roles = "Administrator")] public class ContactModel : PageModel { public string Message { get; set; }
public void OnGet() { Message = "Your contact page."; } } }
Теперь, попасть на страницу Contact вы сможете только при условии, что авторизуетесь с логином someone@somewhere.com и паролем _AStrongP@ssword!123. Метод может не сработать, если при создании администратора будет использован пароль, содержащий запрещенные и не содержащий необходимые символы.

четверг, 29 ноября 2018 г.

Нестандартное (для меня) поведение параметров в контролере asp.net core

Когда-то в Web Api 2 я мог написать такой action:
public class INP { public string value { get; set; } } public string Post(INP con) { return con.value; }
и все отлично работало как с ContentType: application/x-www-form-urlencoded отправленным от клиента, так и с ContentType: application/json
Однако, в asp.net core все не так просто: с вышеприведенным кодом ContentType: application/x-www-form-urlencoded работает, а вот ContentType: application/json оставляет мне просто null в коде. Если обрамлять параметр атрибутом [FromBody], то ситуация меняется: с ContentType: application/json все отлично, а вот с ContentType: application/x-www-form-urlencoded мне вовсе приходит ответ вида 415 Unsupported Media Type
Итак, сам вопрос: как в asp.net core написать action, который бы принимал мне параметр разных ContentType'ов, как это было в Web Api 2? И почему поведение изменилось?


Ответ

Этот вопрос можно решить таким путем: нужно создать две разные Action method-ы, которые смогут специфически байндить данные необходимые для отправки, а затем делегировать обработку вызовов к общему методу.
Например:
public class MyController : Controller { //для ContentType: application/x-www-form-urlencoded [HttpPost] public IActionResult Index(MyClass myclass){ return DoSomething(myclass); }
//и для ContentType: application/json [HttpPost] public IActionResult IndexFromBody([FromBody] MyClass myclass){ return DoSomething(myclass); }
private IActionResult DoSomething(MyClass myclass){ // сделай тут что нибудь с myclass // ... // ... return Json(myclass); } }
Зачем Изменения?
Разве раньше не было попроще? Может быть, но по мнению Дэмиана Эдвардса в сообществе Standup, основная причина это безопасность, в частности - предотвращение Межсайтовой подделки запросов (CSRF)
UPDATE
Вы должны решить эту проблему routing-ом, но если вы попытаетесь отобразить две вышеуказанные действия по одному и тому же маршруту, это приведет к ошибке. Решением этого будет создание пользовательского маршрута и вызов соответствующего метода по заголовку. Я понимаю что это требует больше усилий, чем этого стоит, но они говорят что эти изменения в целях безопасности, я не стал глубоко изучать как именно это предотвращает CSRF. Вы можете погуглить или же посмотреть тут