Я хочу, чтобы иметь возможность возвращать общий ответ от вызовов функций в бизнес-слое моего приложения MVC. Большая часть времени я вижу объект создать функцию выглядеть следующим образомКак вернуть общий ответ и код ответа из всех функций приложения .NET MVC?
public int Create(ICNUser item)
{
return this._repository.Create(item);
}
public void Update(ICNUser item)
{
this._repository.Create(item);
}
В этом случае _repository является хранилищем, который оборачивает рамку сущности.
Это работает отлично для многих случаев, но я хочу, чтобы информация была возвращена, и я хочу иметь переменную успеха/отказа и код ответа, почему это действие не удалось проверить. Я хочу, возможно, иметь возможность вернуть вставленный объект или выбранный объект.
Примером может служить пользовательская функция-создатель, которая возвращает электронное письмо, не может быть пустой ошибкой или, если пользователь уже существует, и на основании ошибки я показываю пользователю другое сообщение.
Проблема, с которой я сталкиваюсь, заключается в том, что я хочу, чтобы модульные тесты охватывали все возможные коды ответа из функции, без необходимости смотреть на код и пытаться выяснить, каковы возможные возвращаемые значения. То, что я делаю, похоже на анти-шаблон. Есть ли лучший способ выполнить все это?
Это то, что у меня есть сейчас.
public IGenericActionResponse<ICNUser> Create(ICNUser item)
{
return this._repository.Create(item);
}
public IGenericActionResponse Update(ICNUser item)
{
return this._repository.Update(item);
}
Интерфейсы
namespace Web.ActionResponses
{
public enum ActionResponseCode
{
Success,
RecordNotFound,
InvalidCreateHash,
ExpiredCreateHash,
ExpiredModifyHash,
UnableToCreateRecord,
UnableToUpdateRecord,
UnableToSoftDeleteRecord,
UnableToHardDeleteRecord,
UserAlreadyExists,
EmailCannotBeBlank,
PasswordCannotBeBlank,
PasswordResetHashExpired,
AccountNotActivated,
InvalidEmail,
InvalidPassword,
InvalidPageAction
}
public interface IGenericActionResponse
{
bool RequestSuccessful { get; }
ActionResponseCode ResponseCode { get; }
}
public interface IGenericActionResponse<T>
{
bool RequestSuccessful { get; }
bool RecordIsNull{get;}
ActionResponseCode ResponseCode { get; }
}
}
реализаций
namespace Web.ActionResponses
{
public class GenericActionResponse<T> : IGenericActionResponse<T>
{
private bool _requestSuccessful;
private ActionResponseCode _actionResponseCode;
public T Item { get; set; }
public GenericActionResponse(bool success, ActionResponseCode actionResponseCode, T item)
{
this._requestSuccessful = success;
this._actionResponseCode = actionResponseCode;
this.Item = item;
}
public GenericActionResponse(bool success, ActionResponseCode actionResponseCode)
{
this._requestSuccessful = success;
this._actionResponseCode = actionResponseCode;
this.Item = default(T);
}
public bool RecordIsNull
{
get
{
return this.Item == null;
}
}
public bool RequestSuccessful
{
get
{
return this._requestSuccessful;
}
}
public ActionResponseCode ResponseCode
{
get
{
return this._actionResponseCode;
}
}
}
public class GenericActionResponse : IGenericActionResponse
{
private bool _requestSuccessful;
private ActionResponseCode _actionResponseCode;
public GenericActionResponse(bool success, ActionResponseCode actionResponseCode)
{
this._requestSuccessful = success;
this._actionResponseCode = actionResponseCode;
}
public bool RequestSuccessful
{
get
{
return this._requestSuccessful;
}
}
public ActionResponseCode ResponseCode
{
get
{
return this._actionResponseCode;
}
}
}}
MVC приложение
public ActionResult ValidateResetHash(string passwordResetHash)
{
IGenericActionResponse result = (IGenericActionResponse)this._userManager.IsValidPasswordResetHash(passwordResetHash);
if (result.RequestSuccessful)
{
Models.PasswordChangeModel model = new Models.PasswordChangeModel();
model.PasswordResetHash = passwordResetHash;
return View("~/Areas/Public/Views/ResetPassword/PasswordChangeForm.cshtml", model);
}
else
{
switch (result.ResponseCode)
{
case ActionResponseCode.RecordNotFound:
{
FermataFish.Models.GenericActionModel responseModel = new FermataFish.Models.GenericActionModel(true, "/Login", "Login", "You have submitted an invalid password reset link.", false);
return View("~/Views/Shared/GenericAction.cshtml", responseModel);
}
case ActionResponseCode.PasswordResetHashExpired:
{
FermataFish.Models.GenericActionModel responseModel = new FermataFish.Models.GenericActionModel(true, "/ResetPassword", "Reset Password", "You have submitted an expired password reset link. You must reset your password again to change it.", false);
return View("~/Views/Shared/GenericAction.cshtml", responseModel);
}
default:
{
FermataFish.Models.GenericActionModel responseModel = new FermataFish.Models.GenericActionModel(true, "/", "Home", "An unknown error has occured. The system administrator has been notified. Error code:" + Enum.GetName(typeof(ActionResponseCode), result.ResponseCode), false);
return View("~/Views/Shared/GenericAction.cshtml", responseModel);
}
}
}
}
Tyree Я все еще перевариваю ваше решение. Я также нашел это СО, что имеет отношение к тому, что вы предложили, в отношении подклассовых перечислений. http://stackoverflow.com/questions/633656/programming-against-an-enum-in-a-switch-statement-is-this-your-way-to-do – codenesium
@codenesium не стесняйтесь задавать любые вопросы. –
@codenesium Это правильно. Я называю это как ограничение типа подкласса. TResponse должен быть подклассом Response. Таким образом, у нас есть доступ к его типу, чтобы мы могли извлечь его имя типа. –