Для чего это стоит, я делаю это по-другому. У успешного вызова есть только объекты JSON. Мне не нужен объект JSON более высокого уровня, который содержит поле успеха, указывающее true и поле полезной нагрузки, которое имеет объект JSON. Я просто возвращаю соответствующий объект JSON с 200 или любым, что подходит в диапазоне 200 для статуса HTTP в заголовке.
Однако, если есть ошибка (что-то из семейства 400), я возвращаю хорошо сформированный объект ошибки JSON. Например, если клиент выполняет POSTING пользователя с адресом электронной почты и номером телефона, и один из них неверен (т.е. я не могу вставить его в мою базовую базу данных), я верну что-то вроде этого:
{
"description" : "Validation Failed"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Invalid phone number."
} ],
}
Важные биты здесь состоят в том, что свойство «field» должно соответствовать полю JSON, которое не может быть проверено. Это позволяет клиентам точно знать, что пошло не так с их запросом. Кроме того, «сообщение» находится в локали запроса. Если оба «emailAddress» и «phoneNumber» были недопустимыми, массив «errors» будет содержать записи для обоих. Тело ответа JSON 409 (конфликт) может выглядеть так:
{
"description" : "Already Exists"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Phone number already exists for another user."
} ],
}
С кодом статуса HTTP и этим JSON у клиента есть все, что им нужно, чтобы ответить на ошибки детерминированным способом и не создавать новый стандарт ошибок, который пытается завершить замену кодов состояния HTTP. Обратите внимание, что это происходит только в диапазоне 400 ошибок. Для чего-либо в диапазоне 200 я могу просто вернуть все, что подходит. Для меня это часто HAL-подобный объект JSON, но на самом деле это не имеет никакого значения.
Единственное, что я подумал о добавлении, - это числовой код ошибки либо в записях массива «ошибки», либо в корень самого объекта JSON. Но пока нам это не нужно.
Статического конструктора вызывает время выполнения и не непосредственно пользовательским кодом. Вы видите это путем установки точки останова в конструкторе и затем выполнения в отладчике. Функция сразу выше его в цепочке вызовов является собственным кодом.
Править: Существует много путей, которыми статические инициализаторы, выполненные в другой среде, чем другой пользователь, кодируют. Некоторые другие пути
В целом, вероятно, лучше не использовать их для чего-либо слишком сложного. Можно реализовать единственный-init со следующим шаблоном:
private static Assembly _assembly;
private static Assembly Assembly {
get {
if (_assembly == null) _assembly = Assembly.GetExecutingAssembly();
return _assembly;
}
}
private static Assembly _calling_assembly;
private static Assembly CallingAssembly {
get {
if (_calling_assembly == null) _calling_assembly = Assembly.GetCallingAssembly();
return _calling_assembly;
}
}
Добавьте блокировку, если Вы ожидаете многопоточный доступ.
Блок. GetCallingAssembly () просто возвращает блок второй записи в стеке вызовов. Это может очень в зависимости от где, как Ваш метод/метод считывания/конструктора называют. Вот то, что я сделал в библиотеке для получения блока первого метода, который не находится в моей библиотеке. (Это даже работает в статических конструкторах.)
private static Assembly GetMyCallingAssembly()
{
Assembly me = Assembly.GetExecutingAssembly();
StackTrace st = new StackTrace(false);
foreach (StackFrame frame in st.GetFrames())
{
MethodBase m = frame.GetMethod();
if (m != null && m.DeclaringType != null && m.DeclaringType.Assembly != me)
return m.DeclaringType.Assembly;
}
return null;
}
Я думаю, что ответ находится здесь в обсуждении статических конструкторов C#. Мое лучшее предположение - то, что статический конструктор становится вызванным от неожиданного контекста потому что:
Пользователь не имеет никакого контроля на том, когда статический конструктор выполняется в программе