Ответы пользователя по тегу ASP.NET
  • Как правильно разделить логику между контроллерами с usecases?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Абстрактно "правильного" варианта реализации нет, всё зависит от конкретных деталей.
    В частности, посмотрите, используют ли ваши методы действий одни и те же внешние зависимости, или каждый - свои. Во втором случае некотоый смысл разнести их по разным контролерам есть: снизить сложность, которую дают лишние, не обусловленые задачей связи (coupling). А первом случае - нет (но может и появиться по другим основаниям).

    А вся эта теория "чистой архитектуры" - она абстрактная. Ее полезно знать, чтобы иметь возможность рассмотреть больше вариантов решения, и видеть больше про возможных подводных камней, а вот фанатично ей следовать не стоит (если, конечно, ваша задача - сделать что-то полезное, а не спихнуть курсовик и т.п.).
    Ответ написан
    Комментировать
  • Почему не удается подключиться к веб серверу?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Вы делаете приложение на ASP.NET Core? В таком случае это означает, что не запустилось приложение. У вас там должна текстовая консоль при запусе выражения вылезать. Посмотрите, что там написано.
    Или в окне Output/Debug - туда это тоже дублируется.
    Ответ написан
    Комментировать
  • Почему получаю System.InvalidOperationException: No authentication handler is registered for the scheme?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Вы неправильно используете метод ControllerBase.Forbid. Передаваемая в него строка (она, как понимаю, преобразуется в массив строк из одного элемента) - это не сообщение об ошибке, а название использованного метода аутентификации.
    Ответ написан
    Комментировать
  • Как корректно завершить webapplication, чтобы вызвался и исполнился до конца IHostLifetime.ApplicationStopping.Register(mymethod)?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Для ответа на вопрос несколько не хватает информации - как у вас организована реакция на отмену IHostApplicationLifetime.ApplicationStoping (что и как делает регистрируемый callback при отмене), какие сервисы вы используете и как они реагируют на отмену того же маркера.
    И IMHO информацию лучше собирать методом проб и ошибок. Самое первое, что вы можете попробовать - это такой вариант. Во-первых, нужно зарегистрировать свой callback последним. А для этого нужно вызвать конструкторы всех сервисов в надежде, чо если они и регистрируют callback на этот маркер, то делают это у себя в конструкторах и только потом регистрировать свой callback (если вы эти сервисы получаете путем внедрения зависимостей через конструктор, это получится автоматически). Во-вторых, нужно выполнить всю работу в своем callback синхронно, в частности, если сообщения отправляются сервисами асинхронно, то подождать завершение каждого (Tasl.WaitAll вам в помощь), а не ждать каждый через await (или явно - используя ContinueWith - но сейчас так никто не делает).
    Идея рассчитана на то, что реализация IHostApplicationLifeTime отменяет (ЕМНИПпроверено в исходниках) этот маркер простым Cancel и ждет завершения отмены (и в документации об этом ожидании смутно упомянуто, т.е., это не хак, зависящий от реализации) , а Cancel вызывает все зарегистрированные callback синхронно, в порядке, обратном регистрации (это ЕМНИП тоже документированнное поведение).
    Попробуйте для начала так, прежде чем применять более крутые меры (например, подменять реализации IHostLifeTime и IHostApplicationLifetime(UPD: погорячился, эту реализацию подменять нельзя, там обязан быть класс ApplicationLifetime) - технически это реально, но лучше такое оставить на потом).
    Если не прокатит, я ответ постараюсь продолжить.

    PS По поводу способов закрытия приложения. AFAIK остановка через "красный квадратик" в VS и закрытие окна консоли вызывает просто уничтожение процесса, и это не перехватывается (могу ошибаться, конечно). А вот закрытие по Ctrl+C отлично перехватывается ConsoleLifeTime (обычно испольуемая для консольных приложений реализация IHostLifetime), так что именно этот способ закрытия можно считать штатным. А вообще по жизни, 100% срабатывающих способов реакции на прекращение работы приложения нет - ибо прекращение может быть вызвано такой причной, как пропадание питания (особенно - если вследствие перерубания кабелей топором ;-) ).
    Ответ написан
    1 комментарий
  • Как написать свой кастомный EditorFor и получить значение свойства модели?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    У вас в поле _helper класса FormHelper<TModel> конструктор сохраняет ссылку на интерфейс IHtmlHelper<TModel>.
    Этот интерфейс содержит свойство ViewData типа ViewDataDictionary<TModel>. А в этом типе реализовано свойство Model (типа TModel), которое даст вам ссылку на экземпляр класса (типа TModel) модели для представления/страницы.
    Ну, а дальше, раз вы знаете имя нужного вам свойства объекта и имеете ссылку на экземпляр этого объекта, то можете получить значение этого свойства: либо через составление с последующей компиляцией и вычисление выражения, возвращающего его значение, либо через отражение.
    Как-то так.
    Ответ написан
    1 комментарий
  • Как удалить сессию из БД после истечения срока?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    В ASP.NET Core есть стандартный механизм сеансов (ISession): https://learn.microsoft.com/aspnet/core/fundamenta...
    Работает он на базе распределенного кэша (IDistributedCache), который штатными средствами можно базировать на MS SQL и на Redis (и, возможно, есть дополнительные сторонние пакеты для базирования на других СУБД,). Идентифкатор сессии хранится в куки (настраеваемой), по умолчанию - HTTP-only (но это настраивается).
    Механизм устаревания сеансов там есть, параметры тоже можно настроить.
    Кароче, если нет причин обязательно делать свой велосипед (типа, для учебной задачи) можно использовать этот стандартный механизм.
    Правда идея использовать этот механизм именно для авторизации у меня вызывает некоторые неясные опасения: он, вообще-то, не для того сделан. А именно для авторизации (плюс аутентифкация) в ASP.NET Core тоже есть штатное решение (Identity и политики авторизации). И вообще, аутентифкация/авторизация - это такое место, где легко накосячить, а потому лучше там обходиться без своих велосипедов.
    Ответ написан
    3 комментария
  • По какой причине появляеться SqliteException: SQLite Error 19: 'NOT NULL constraint failed?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Исправьте вот здесь:
    [Column("profilePicturePath")]
        public string? ProfilePicturePath { get; set; }

    Пояснение. В документации по EF Core написано:
    Если включены ссылочные типы, допускающие значение NULL, свойства будут настроены на основе nullability C# для типа .NET: string? будут настроены как необязательные, но string будут настроены по мере необходимости.

    В современных шаблонах проектов nullability включена по умолчанию, так что ваш тип свойства string EF понимает как то, что соответствующая колонка записи должна иметь ограничение NOT NULL. А потому вам следует использовать в качестве типа свойства string? .
    Ответ написан
    1 комментарий
  • Можно ли использовать excel файлы для генерации представлений в ASP проекте?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Идея генерировать содержимое HTML на основе внешних данных - она правильная. И шаблоны Razor (.cshtml) предоставляют для этого очень удобные средства, кстати. Так что хранить данные в самих шаблонах - это неправильная идея (вы в этом уже убедились, да).
    По поводу вашего предложения, как зранить данные, у меня есть совет: экспортируйте эти файлы из Excel в формат техта с разделителями (например, CSV, а я лично предпочитаю в качестве разделителей знаки табуляции). Это - обычные тектовые файлы, которые можно, при необходимости, править и без Excel (хоть в Блокноте), а для больших правок - импортировать в Excel. И всякие средства для контроля версий, типа Git - они с текстовыми файлами работают значительно лучше, чем с файлами excel.

    PS Как вам правильно написал в комментарии Sergey В. , для хранения данных лучше использоваь базу данных. Вы особенно это оцените, если функциональность проекта будет расширяться. А внешние файлы - хоть Excel, хоть текстовые - это эрзац-решение. Но если для вас это терпимо, а использовать БД в проекте вам сложно, то используйте файлы.
    Ответ написан
  • В каких случаях создавать новые контроллеры?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Одно из сображений, касающееся производительности. Контролллер - это класс, который создается каждый раз для обработки запроса.
    Поэтому имеет смысл смотреть на сервисы-зависимости в его конструкторе (параметры конструктора, которые извлекаются из контейнера сервисов): если действия этого контроллера используют разные зависимости, особенно - с временем жизни Scoped (DatabaseContext, к примеру) или Transient, то эти действия - хорошие кандидаты на перенос в отдельный(е) контроллер(ы).
    Ответ написан
    Комментировать
  • Почему некорректно работает параметр маршрутизатора Razor Pages?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Параметры маршрута привязываются к параметрам метода обработчика страницы по имени, т.е. их имена в директиве @page в шаблоне страницы и в списке параметров метода в коде должны совпадать.
    А у вас в @page используется id, а в списке параметров OnGet - pageId. Переименуйте что-нибудь, чтобы имена одинаковые были - и будет вам счастье.
    Ответ написан
  • Зачем нужен Service Locator?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Не легче ли внедрение делать через конструкторы?

    А вы не задумывались над тем, кто и как будет разрешать зависимости для конструкторов?
    В нынешнем ASP.NET Core этим занимются каркасы приложений ("фрейворки", от английского framework). И делают они это как раз через контейнер сервисов (либо напрямую через GetService, либо через ActvatorUtilities).
    Но есть области в ASP.NET Core , которые фремворками не закрываются - наример, в конвейере обработчиков запроса (middleware), там где требуется делегат типа RequestDelegate. И там без прямого обращения к контейнеру сервисов не обойтись.
    Ответ написан
    Комментировать
  • Как ограничить количество запросов на сервер при создании поисковика?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Не то, чтобы ответ, но идея ответа. И если чо непонятно - могу в каментах поуточнять.
    Со стороны тыла (на C#) можно ограничить число параллельных запросов в целом к сервису безо всяких там плагинов, а саморучно сделанным велосипедом: семафором (например, SemaphoreSlim, как самым модным в этом сезоне). Либо сделать его статическим, либо (чтобы веру в IoC свято блюсти и модульные тесты делать) - запихнув в Singleton-сервис с теми же свойствами/методами, что и у семафора используются, и получать этот сервис через конструктор (передавать через DI - в бою, напрямую - в тесте).
    Для семафора(сервиса) устанавливаете максимальное число параллельно выполняемых запросов в качестве начального значения. При входе в обработчик захватываете семафор (Wait/WaitAsync, таймаут - по вкусу), при выходе (лучше - в блоке finally того try, который начинается после захвата семафора) - освобождаете (Release).
    Таймаут выставляете в зависимости от поведения фронта: какие у него у самого таймауты на запрос (в том числе - на повторение) и как он реагирует на задержку ответа и на всякие разные коды статуса HTTP в ответе. В целом, стратегии тут две. Первая - пытаться захватывать семафор с коротким таймаутом и в случае неудачи - возвращать другой код статуса, кроме ОК, чтобы сказать фронту, что он не прав. Вторая - тормозить лишние запросы таймаутами. Кароче, без знания вашего фронтового плагина тут точно не скажешь, а я его знать не знаю и знать не хочу.
    Ответ написан
    Комментировать
  • Как должен быть путь для контроллера?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Если вы, как у вас написано, передаете название страны и города через путь в URL, то параметры метода Action для URL второго формата должен привязываться к переменной маршрутизации, примерно так:
    [HttpGet("{country}/{city}")]
    public IActionResult ActionMethod([FromRoute] String country, [FromRoute] String city) 
    {
      //... method code
    }

    [FromRoute] можно и не писать, если параметров запроса (то, что после '?' в URL) нет: привязка по умолчанию выберет следующим источником переменные маршрутизации.
    PS Можно обойтись одним методом действия (Action), если указать что city - параметр необязательный
    [HttpGet("{country}/{city?}")]
    public IActionResult ActionMethod([FromRoute] String country, [FromRoute] String? city) 
    {
     if(city==null) {
      //... method 1 code 
     }
     else {
      //... method 2 code 
     }
    }
    Ответ написан
    Комментировать
  • Почему прекращается работа BackgroundService?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Работа фонового сервиса у вас прекращается потому что у его метод ExecuteAsync дожидается инициализации статической переменной WebView (она содержит ChromiumWebBrowser, открытый на странице https://web.watsapp.com) а потом ничего не ждет, а просто завершается. А что там у вас происходит с браузером, код вашего фонового сервиса не контролирует.
    PS Я не вижу ваш остальной код, но могу предположить, что вам для работы программы этот фоновый сервис не нужен, т.к. вся работа с экземпляром CefSharp идет через упомянутую статическую переменную.
    Ответ написан
    3 комментария
  • ASP.NET Core 6 Как устранить ошибку при выполнении команды update-database?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    'MultipleActiveResults=True'

    Уберите эти одинарные кавычки.
    Ответ написан
    Комментировать
  • Почему сервер не разрешает [delete] метод (ошибка 405)?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Общий ответ - какой-то другой обработчик перехватывает запрос.

    Конкретный ответ зависит от того, как хостится приложение и от остального его кода. Если приложение работает через IIS(хостится на нем или опубликовано через него), то этим обработчиком часто является модуль WebDAV, и его надо отключить. Самый простой вариант, как это сделать - второй ответ этого вопроса: https://stackoverflow.com/questions/55736265/getti..., подробности, если интересно - https://learn.microsoft.com/ru-ru/aspnet/web-api/o...
    Ответ написан
  • Как адаптировать MapPost в метод ControllerBase?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Вынесено из комментариев (не туда запостил):

    Если бы я был контроллером API на MVC, я бы тоже так же ответил: "что за фигню вы мне прислали?" (в протоколе HTTP это обозначается кодом статуса 400).
    Контроллер API ждет, что вы ему пришлете, нечто, содержащее значение для параметра message вашего метода действия. Если вы посылаете в формате JSON, то - объект с полем message: тогда он привяжет значение этого поля входному параметру метода действия, который имеет то же имя message, как у вас.
    Потому в запросе POST надо слать объект с этим полем. Например - в уже сериализованном (строковом) формате:
    string content = "TestContent";
    Но можно в качестве content использовать и объект с полем message, например - анонимного типа:
    var content = new { message = "TestContent" };
    - PostAsJsonAsync сумеет превратить это в JSON.

    И да, к контроллеру на Minimal API из вашего первого комментария все это точно так же относится.
    Ответ написан
    Комментировать