Задать вопрос
Ответы пользователя по тегу C#
  • Почему данные из представления не передаются в модель в ASP.NET?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Источник проблемы с привязкой действия: в теле ответа у вас нет ничего, кроме antiforgery token. Так что надо смотреть на клиенте HTML, который сгенерил движок представления - похоже, кривизна там, форма сгенерена неверно.
    Перед просмотром имеет смысл включить для окна/вкладки, где будет страница с формой, средства отладки браузера (F12) и смотреть ошибки, которые они выведут - может, они что найдут в авттоматическом режиме.

    Конкретную причину ошибки я пока не опознаю. Подозрение у меня вызывает атрибут asp-for=Id для первого элемента формы: значения атрибутов tag helper чисто по синтаксису надо указывать в кавычках, потому что они подчиняются тому же синтаксису, что и обычные атрибуты HTML. Но в этом ли причина, утверждать не могу.
    Ответ написан
  • Можно ли использовать Expression без типов-делегатов?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Вкратце: не заморачивайтесь.
    В ремесле программирования есть полезный принцип, обозначаемый англоязычным сокращением YAGNI, что в переводе означает "Вам это не понадобится." Согласно этому принципу, раз вы не знаете, как можно использовать Expression с параметром-типом не являющимся делегатом, то вам вряд ли понадобится его так использовать.
    А проверки параметра-типа там нет, скорее всего, потому что эта функциональность (она называется Expression trees) появилось давно, больше 15 лет назад, в .NET Framework 3.5, а тогда в .NET проверки параметра-типа ЕМНИП не было.
    Но, подозреваю, что попытка использовать в качестве TDelegate не тип-делегат просто приведет к ошибке: почти наверняка - при попытке получить исполняемый код из выражения (метод Compile), а, возможно, и раньше - или при попытке создания объекта, или даже на этапе написания кода или компиляции: ее может (да или нет - не проверял) обнаружить анализатор при компиляции исходного кода и даже IntelliSense. И подозреваю, что при попытке обойти дерво такого объекта Expression tree (это - альтернативный способ использования этой функциональности), тоже будет ошибка - ибо выражение получается бессмысленным.
    В любом случае, истиной в последней инстанции является исходный код. Если вам так уж захотелось узнать, что будет - читайте исходный код: он лежит на GitHub, ссылка есть в документации по классу в learn.microsoft.com (сразу предупреждаю: там все сложно).
    Ответ написан
    Комментировать
  • Как реализовать потоковое заполнение массива другим потоком?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Сколько там недочетов. потенциальных ошибок. неверных решений?

    1. У вас намешаны синхронная - в с одном потоке с блокировками (Wait, Sleep) - и асинхронная (async/await) многозадачность Теоретически, совмещать их можно, но лучше остановиться на каком-то одном подходе - легче будет. Синхронное выполнение задач (каждая - в своем потоке, который она блокирует по необходимости) - это проще, но асинхронное выполнение (при которм поток не блокируется, а освобождается, а задача планируется для продолжения после завершения операции в свободном потоке) позволяет получить больше производительности. Вот и выбирайте, что вам нужнее.
    2. Для синхронизации используйте не переменные (а, к примеру, isRun у вас используется именно для этого), а объекты синхронизации. В частности, isRun следует заменить на объект синхронизации. Для синхронного выполнения лучше всего IMHO подойдет ManualResetEventSlim. для асинхронного - что-нибудь, на чем можно сделать await (например, TaskCompletionSource.Task).
    3. Любой доступ к совместно используемым в разных задачах объектам(ресурсам) следует синхронизировать путем захвата связанного с ресурсом объекта исключающего доступа. Для синхронного выполнения подойдет оператор lock (вижу, что вы его уже используете). Для асихронного выполнения lock можно использовать, но - только если в его теле нет await (и компилятор вам не позволит нарушить это правило). Не пытайтесь обойти это правило, используя вместо lock другие объекты синхронизации, подразумевающие захват владения на уровне потока (Monitor, Mutex...) - компилятор всего лишь не сможет вам помешать сделать ошибку. В таком случае для синхронизации можно использовать SemaphoreSlim, но это требует понимания и аккуратности, поэтому подробности пока не пишу.
    Думаю, пока этой информации к размышлению вам хватит.
    Ответ написан
    1 комментарий
  • Поиск куда можно добраться по графу за время?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Алгори́тм Де́йкстры (англ. Dijkstra’s algorithm) — алгоритм на графах, изобретённый нидерландским учёным Эдсгером Дейкстрой в 1959 году. Находит кратчайшие пути от одной из вершин графа до всех остальных.

    Здесь
    Ответ написан
    Комментировать
  • Как в C# в динамике задать у обощенного класса тип поля хранимого значения?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Для задания динамического типа для поля в C# есть ключевое слово dynamic. Но на самом деле, это - object, просто для него компилятор автомтически реализует преобразование типов (и ещё кое-что - см. [документацию](https://learn.microsoft.com/en-us/dotnet/framework...) она хотя и по Framework, но многое из этого есть и в .NET(Core и современном))
    Ответ написан
  • Возможно ли решить по другому вывод информации?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Простейший способ решить вашу задачу - найти того, кто ее вам решит: человека - за деньги, по дружбе и пр. - или ChatGPT и т.п. LLM. Человека искать - это не здесь (если на Хабре, за деньги - то есть раздел Freelance).

    Если же вам почему-то хочется решить задачу самому, и нужна подсказка, то, прежде всего, задачу надо сформулировать, примерно - как в математике: что дано и что требуется получить. А потом - задать конкретный вопрос по тому, что мешает вам решить. Если это не сделать, то придется вам ждать помощи телепата или ясновидящего.

    В частности (я не телепат, но попробую угадать), если вам мешает неудобная работа с TimeSpan, то стоит вспомнить (или узнать), что он представляет собой число фиксированных мелких промежутков времени, именуемых tick. Вы можете прочитать это число в его свойстве Ticks, работать с ним как с обычным числом - не только сравнивать, но и умножать, делить, складывать, вычитать - а потом, если надо, перевсти обратно в TimeSpan методом TimeSpan.FromTicks.

    PS Если будете описывать задачу, лучше всего пользуйтесь не автоматически даваемыми названиями элементов интерфейса - dateTimePicker2, textBox6 и пр. - а названиями указывающими на их смысл - лучше всего их переименовать соответствующим образом, это - крайне рекомендованная практика при программировании вообще.
    Ответ написан
    2 комментария
  • Как использовать Bitmap в .NET в 7.0?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Либо использовать для проекта Windows Forms, либо явно добавить в проект нужный пакет System.Drawing.Common
    Ответ написан
  • Стоит ли разделить микросервис Account на микросервис по авторизации и микросервис пользователей?

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

    Микросервис никому ничего не должен. Даже - существовать отдельно от приложения.
    И в вашем приложении, скорее всего, он тоже не нужен, а список пользователей и авторизацию можно сделать частью самого приложения. Но если вы хотите потренироваться с микросервисной архитектурой, то смотрите по своей задаче.
    Если у вас нет пользователей, которые просто числятся и никогда не авторизуются, то отдельный микросервис для пользователей вам точно не нужен. Потому что в таком случае атрибуты авторизации - это неотъемлемая часть сущности "пользователь".
    В противном случае возможны варианты, но нужно взвесить все за и против. В частности - возможную потерю целостности, когда какие-нибудь авторизационные данные не будут соответствовать ни одному пользователю.
    Ответ написан
    Комментировать
  • Батчинг входящих запросов с неблокирующим ожиданием?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    А вам точно это нужно?
    Потому что тут у вас появляется нюанс, который не совсем ложится на схему работы веб-приложения: у ваших отдельных запросов появляется общее состояние. Как минимум, это - накапливаемый пакет запросов, а ещё, наверное, в это состояние входит нечто общее для всех запросов для работы с БД: подключение или, если используется Entity Framework, DbContext. Это общее состояние придется как-то хранить, регулировать доступ к нему (DbContext к примеру, параллельный доступ не поддерживает в принципе), и вовремя это состояние удалять. Если посмотреть на стандартные механизмы ASP.NET Core, то сессия (ISession) для этого, наверное, не подойдет - там можно хранить только сереализуемые в байты пассивные объекты, и насчет регулировки доступа там непросто. Подойдет концентратор (Hub) SignalR, у которого есть сохраняемый между вызовами контекст подкючения - но ради него, скорее всего, потребуется менять способ вызова API из браузера: у него там своя клиентская библиотека.
    Ну и, по-любому, как-то надо реализовывать активную часть - которая, собственно, отслеживает пакет изменений и вовремя отправляет его в БД.
    Ваша идея
    Шедуллер в фоне будет периодически читать коллекцю объектов на запись и устанавливать результат выполнения в соотвтвующий TaskComplitionSource.

    мне не совсем нравится. Зачем периодически? Kучше чтобы эта активная часть срабатывала по факту добавления запроса в пакет - например, асинхронно ожидала Task от TaskComplitionSource. который метод добавления запроса завершал бы по факту добавления завершающего пакет запроса. Но и завершение по таймауту тоже предусмотреть надо - по жизни оно всякое бывает: обычно для таких целей используется WaitAny для комбинации основной ожидаемой задачи с Delay по таймауту.
    Ну, а ещё требуется, наверное, чтобы для каждого пользователя состояние было свое. В принципе, это делается, но надо делать. Для SignalR для этого можно использовать Hub.Context.Items - это словарь, который может содержать произвольные объекты, и сохраняется на время действия всего подключения.

    А ещё у меня, в принципе, есть своя самодельная библиотека, которая решает ту же задачу - сохранение контекста сеанса, в том числе - активного, с выполняющимся кодом. Я описывал ее недавно в статьях (кроме основной статьи есть дополнительная) на Хабре. Можете попробовать её, если переделывать API не хочется: она вполне годится для работы с API на базе MVC API Controller. или Minimal API. В принципе, она заточена немного под другую задачу - получние и возврат дополнительных результатов в фоне, но для вашей задачи она тоже подойдет. Напишу тут сразу технические подробности как использовать: ссылку на активную часть, собирающую и отправляющую пакет, можно хранить в IActiveSession.Properties, точно так же, как если бы вы хранили ее в Hub.Context.Items, а обработчик завершения, который прибирает за собой (в SignalR его место в OnDisconnect) - привязать к IActiveSession.CompletionToken через его метод Register. В общее для всез запросов состояние входит свой контейнер сервисов со своей областью действия в течение всего существования состояния, так что, если для работы с БД требуется Scoped-сервис из DI-контейнера, то его можно получить оттуда (в дополнительной статье написано, как, а также написано, как защититься от нежелательного одновременного доступа к такому сервису).

    Только вот библиотека эта, естественно, ни разу не стадартная, use at your own risk. Но если попробуете ее, мне будет интересно, что получилось. В том числе - и обнаруженные ошибки, заодно я и для вас их исправлю :-) .

    PS И неплохо было бы IMHO, чтобы дальнейший диалог, если он будет, шел на русском языке, без "батч", "эвейтить", "шедулер" и прочих транслитераций, IMHO лучше уж по-английски писать, если перевод неизвестен. А то я человек старый, мне читать этот пиджин тяжеловато.

    PPS А ещё благодарю за идею, о том, в какую сторону мне развивать мою библиотеку.
    Ответ написан
    1 комментарий
  • Как выполнить функцию после завершения всех задач?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Используйте метод Task.WaitAll
    Ссылки на все эти задачи, при этом надо, кончено не бросать без присмотра при перезаписи переменной outer, а сохранить (например, в массив Task[])
    Ответ написан
    Комментировать
  • Как правильно разделить логику между контроллерами с usecases?

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

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

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    SomethingFuncCatch().Wait();
    В Wait дополнительно можно передать таймаут и/или CancellationToken (см. описание метода Task.Wait ).

    Только вот, боюсь, что вы не дождетесь когда закончится цикл
    while (i > 0)
    {
        Console.WriteLine("NewProcess started");
        i = i--;
    }

    Ибо вы в нем пытаетесь присвоить i то значение, которое было до уменьшения на 1.
    Ответ написан
  • Нормально ли использовать var вместо явной типизации в C#?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Вынесено из комментариев.
    Василий Банников , ну, что вам на это сказать?
    Сильно легче код писать таким образом.
    Писать - да, читать - it depends, как говорят англичане.

    Если тебе сложно понять смысл кода без типов - значит кто-то плохие имена дал переменным.
    А разве в legacy 4-5-летней выдержки, над которым поработало много программистов, хороших и разных, по-другому бывает? А ещё имена могут дать хорошие, понятные - но основанные на системе понятий, которая нетривиальна и не попала при этом в документацию. Чтобы понять, о чем я - попробуйте почитать исходники подсистемы маршрутизации в ASP.NET Core. лучше всего - после работы с чем-нибудь типа MVC или Razor Pages: сомневаюсь, что вы сразу въедете, что Model там и Model тут - это разные Model.

    А ещё бывает, что методы называются почти одинаково, но типы значений у них разные. Пример: builder.Services.AddOptions() и builder.Services.AddOptions<TOptions>() из кода конфигурирования контейнера сервисов, методы расширения IServiceCollection для Option Patterns - типы возвращаемых значений у них разные. А их ещё любят цеплять друг к другу к таким же методам через точку - вот и смотри потом, чой-то в ConfigureOptions какие-то лишние параметры вылезли.

    с анонимными типами без var работать было бы очень сложно.
    Правильный вопрос - зачем вообще заставлять работать с анонимными типами? Подозреваю, что их из-за маршрутизации в MVC завезли - как типы параметров, вместо того, чтобы передавать в методы генерации ссылок вместо IDictionary<String,Object>, как это оно там реально требуется. Но, в Microsoft решили, видимо, тогда не делать инициализаторы для словарей (при том, что потом всё равно сделали, не отвертелись), а притащить вместо них анонимные типы (интересно откуда - неужели прямо из JS?). Но это не точно. (Ага, в комментарии мне напомнили про LINQ)

    Тренд говорит об обратном - автоматический вывод типов сейчас есть практически во всех статически-типизированных языках в том или ином виде.
    Это потому что сейчас главное - быстрее писать MVP, для веба - особенно. Ну, а потом можно сказать волшебное слово: "Legacy".

    Ну и помни ещё, что ты же не в блокноте код пишешь
    Но читаешь-то ты его не только в IDE. В частности, MS в своей документации на сайте в примерах очень любит писать var - вот и выбирай потом, что делать: лезть прямо сразу в документацию по API (а ссылки отнюдь не прилагаются) или рисковать упустить что-то важное? А если ещё учесть, что сейчас принято документацию ограничивать примерами (MS любит, да) - оно вообще весело.

    Но, с другой стороны, автор вопроса, похоже, с трех- и более этажными дженериками ещё не сталкивался (ну, или забыл, как они выглядят) - там без var тоже грустно.
    Как-то так
    Ответ написан
    2 комментария
  • Миграция вылетает по Stack Overflow. Есть ли ограничение на объем данных в миграции?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Причина ошибки, как пишется в сообщении о ней - переполнение стека. Размер стека для потогков определяется процессом, в котором работает приложение. Обычно он фиксирован и записан в заголовке .exe. Если при размещении веб-приложения в своем процессе (так делается запуск из Visual Studio) стека хватает, то настройте размещение приложения вне процесса и в IIS: документация - здесь, по умолчанию AFAIK для IIS используется размещение приложения ASP.NET Core внутри его рабочего процесса, и используется размер стека этого рабочего процесса.

    PS А вообще, я бы на вашем месте пересмотрел код миграций и использовал стек (локальные переменные методов имеющие тип значений, память, отводимая через stackalloc и т.п.) в нем по минимуму. Потому как требования к памяти приложения имеют свойство расти со временем, а стек задается фиксированной величиной.
    Ответ написан
    Комментировать
  • Как добавить одно поле множеству классов без применения наследования и добавления поля в каждый класс по отдельности?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Привыкли к миксинам в языке с динамической типизацией? В C# их нет, и вряд ли будут, потому что типизация тут статическая. И приемы программирования - соответственно, другие.

    В частности, чтобы добавить дополнительное свойство (или метод) в классы из разных иерархий наследования, используйте интерфейс. Примерно так (примеры - на основе кода из комментариев):
    public interface IChosable {
        bool IsChosen {get; set;}  //Желательно имена писать таки на английском правильном
                                                 // а не ломаном. А то глаза режет.
                                                 //Ну, или хотя бы - по русски транслитом: 
                                                 // Vybrano вместо IsChoised - и то лучше, IMHO
    }
    
    //...
        public class ViewedDirectoryData : DirectoryDataEntity, IChosable
        {
            public bool IsChosen {get; set;}  
        }
    
        public class ViewedOutputData : OutputData, IChosable
        {
            public bool IsChosen {get; set;}  
        }

    Но свойства, таки да, придется определять в каждом классе, реализующем интерфейс (но можно перенести их, вместе с указанием реализации интерфейса, в базовые классы иерархий).

    Удобство тут в том, что ссылку на любой из классов, реализующих интерфейс, можно привести к типу интерфейса - тогда и статический контроль типов сохраните, и работать со всем этими классами можно будет единообразно.
    Ответ написан
  • Как создать экземпляр экземпляра класса?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Вы неправильно понимаете класс enum. enum - это не класс, а ключевое слово языка C#.

    PS
    И я задумался:
    Надо не думать, и даже - не знать. Надо - уметь применять. Подумайте, какую практическую задачу вы хотели решить этой задумкой? Если такой задачи нет - не забивайте себе голову. А если желаете забить себе голову чисто для себя чем-нибудь абстрактным, то для этого лучше всего подойдет философия, а не IT.
    Ответ написан
    Комментировать
  • Как сделать Mock на приватное поле типа Dictionary для Integration tests или как можно проверить, что его метод был вызван?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Сделайте фабрику для экземпляра, реализующего кэш, и передавайте через конструктор её, в виде интерфейса. Тогда кэш у вас будет частным, действующим только внутри класса, но конкретная его реализация будет задаватьс снаружи. И все будет по фэн-шуюSOLID
    Для теста передайте в конструктор имитатор ("мок") этой фабрики, который создает и возвращаетнужный вам имитатор кэша.

    PS Стндартная для .NET имплементация кэша в памяти - это MemoryCache, он реализует интерфейс IMemoryCache. Только вот самому его имитировать нетривиально, поскольку у него есть особенность в поведении: его элемент (ICacheEntry) сохраняется в кэше по факту очистки (вызову Dispose() ). Я про это даже статью на Хабре написал.
    Ответ написан
    2 комментария
  • Как предотвратить изменение пользователем данных во время выполнения async метода сохранения этих данных?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Простейший вариант: копируйте (синхронно) в обработчике нажатия кнопки данные, которые вы сохраняете, в другое место, а там пользователь пусть хоть обизменяется: на сохраняемые данные это уже не повлияет. Если данных вдруг много, то тогда уже придется синхронизировать доступ к ним (для асинхронной синхронизации подходит SemaphoreSlim.WaitAsync/Release, а если вы можете позволить себе блокировку потока UI, то и lock сойдет). Есть и более сложные схемы - копировать только те данные, которые пользователь собрался изменить, и сохранять в таком случае именно их, а не данные из ViewModel ("копирование при записи"). Короче, дерзайте: вариантов много.
    Ну, а вариант с ползунком сам по себе ненадежен: пользователю доверять нельзя. Но как подспорье, вместе с блокировкой изменения - годится.
    Ответ написан
    Комментировать
  • Как заставить объект Moq возвращать разные значения при повторных прогонах теста?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Есть подозрение, что при каждом вызове тестового метода с новым параметром экземпляр вашего тестового класса каждый раз создается заново, вместе с новым экземпляром имитатора (Mock> _ratingRecordRepositoryMock; ) . В пользу этого говорит и то, что вы при каждом вызове заново настраиваете имитатор заново, а если бы экземпляр имитатора уже использовался, вы бы получили ошибку.

    Проверить просто: поставьте точку остановки (или воткните отладочное сообщение) в конструктор тестового класса.
    Ответ написан
    2 комментария
  • Как в C# на этапе AddCookie[options.Events.OnValidatePrincipal] проверять активность сессии пользователя в стороннем auth-server?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Подскажите, как делают refresh_token взрослые дяди в многопоточке.

    Если нужен ответ на это конкретный вопрос, причем если имеется в виду не просто многопоточка, а асинхронная, с await без блокировки потока - то на это есть такой SemaphoreSlim. Делается примерно так (надеюсь, идея будет понятна)
    //Попадаем сюда после получения существующего access token и выявления, что он просрочен
        SemaphoreSlim sem = GetSemaphore(clientId); 
       await sem.WaitAsync(); //timeot и CancellationToken добавить по вкусу
       try {
         //Получаем существующий access token повторно - вдруг его уже кто-нибудь до нас обновил 
        //   (используем double check pattern)
        //Если это не так,  выполняем тут всю логику обновления access token
      }
      finally {
          sem.Release(); //SemaphoreSlim - не мьютекс, сам не освободится в случае чего
      }


    GetSemaphore реализовать можно по-разному. Можно один на все приложение: static или Singleton - это если нагрузка небольшая.
    А можно кэшировать семафоры по одному для каждого пользователя (т.е. свой семафор для каждого clientID), чтобы пользователи не толклись около одного семафора на всех.
    Главное, чтобы этот семафор создавался с начальным значением 1 - тогда он будет пускать пользователей по одному.

    Ну, а если все делать без асинхронности, в одном потоке, блокируя его при необходимости (т.е. без await), то способов много. Простейший - блок lock вокруг кода обновления маркера доступа (access token), есть такде Monitor, Mutex, тот же Semaphore (хоть со Slim, хоть без)...
    Ответ написан
    1 комментарий