更新 - 由于我方缺乏解释,我改写了帖子。
您如何看待使用代码约定在无效输入上抛出异常? (我正在根据我的服务合同进行编码,该合同要求UserName不为空或包含空格)
MembershipServiceContracts.cs - 位于子文件夹中的服务层
[ContractClassFor(typeof (IMemberShipService))]
internal abstract class MemberShipServiceContracts : IMemberShipService
{
#region IMemberShipService Members
public MembershipCreateStatus CreateUser(string userName, string password, string email)
{
Contract.Requires(!String.IsNullOrWhiteSpace(userName), "Test");
Contract.Requires(!String.IsNullOrWhiteSpace(password));
Contract.Requires(!String.IsNullOrWhiteSpace(email));
return default(MembershipCreateStatus);
}
#endregion
}
MembershipService.cs - 位于我的服务层
[ContractClass(typeof (MemberShipServiceContracts))]
public interface IMemberShipService
{
MembershipCreateStatus CreateUser(string userName, string password, string email);
}
public class MemberShipService : IMemberShipService
{
private readonly MembershipProvider _provider;
public MemberShipService()
: this(null)
{ }
public MemberShipService(MembershipProvider provider)
{
_provider = provider ?? Membership.Provider;
}
#region IMemberShipService Members
public MembershipCreateStatus CreateUser(string userName, string password, string email)
{
MembershipCreateStatus status;
_provider.CreateUser(userName, password, email, null, null, true, null, out status);
return status;
}
#endregion
}
AccountController.cs - 位于UI层
现在这是有趣的部分......
我应该使用:
[Authorize(Roles = "Developer")]
[HttpPost]
public ActionResult Create(CreateUserViewModel model)
{
if (!String.IsNullOrEmpty(model.UserName))
{
throw new ArgumentException("UserName May not be null or contain only white spaces.", model.UserName);
}
if (!String.IsNullOrEmpty(model.Password))
{
throw new ArgumentException("Password May not be null or contain only white spaces", model.Password);
}
if (!String.IsNullOrEmpty(model.Email))
{
throw new ArgumentException("Email May not be null or contain only white spaces", model.Email);
}
if (!ModelState.IsValid)
{
return Json("Model validation failed");
}
MembershipCreateStatus newUser = _memberShipService.CreateUser(model.UserName, model.Password,
model.Email);
return Json(newUser != MembershipCreateStatus.Success ? "Failed" : "Success");
}
或:
[Authorize(Roles = "Developer")]
[HttpPost]
public ActionResult Create(CreateUserViewModel model)
{
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(model.UserName),
"UserName May not be null or contain only white spaces.");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(model.Password),
"Password May not be null or contain only white spaces");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(model.Email),
"Email May not be null or contain only white spaces");
if (!ModelState.IsValid)
{
return Json("Model validation failed");
}
MembershipCreateStatus newUser = _memberShipService.CreateUser(model.UserName, model.Password,
model.Email);
return Json(newUser != MembershipCreateStatus.Success ? "Failed" : "Success");
}
如果未满足CreateUser()方法的代码合同,则抛出异常?
提前致谢。
答案 0 :(得分:7)
代码合同中的失败表明您的代码存在应该修复的严重错误。它不会取代用户输入的验证。相反,您将首先验证您的用户输入,然后在确定有效时尝试处理数据(否则提示用户重新输入)。如果您不满足目标合同与您的有效数据,那么将抛出一个无法捕获的异常,因为您显然有一个错误。
我希望它会成为一颗银弹,但很快意识到我仍然需要我的验证。在那之后,我逐渐变得非常喜欢代码合同将取代我所有常用的守卫代码的方式。
想想你会得到一个NullReferenceException(对我来说太多了!)。代码合同可以消除这种痛苦。
R上。
P.S。另外,不要使用契约来验证安全敏感数据,因为代码契约可以在运行时关闭......
答案 1 :(得分:4)
我不敢说:这取决于您希望如何使用代码合同。
您最好查看user manual部分“使用指南”。这是一个小摘录:
最简单地使用合同工具 如果你决定不需要的话 执行参数验证 发布版本中的运行时(用法1)。 在这种情况下,您使用合同 开发过程中的工具,但不是 装运的位。记住,你可以 发运合同参考组件 以及你的释放位18 客户端可以获得运行时检查 你的参数验证 通过call-site需要调试构建 检查。第二个最简单的方法 如果你需要参数验证 您的发布版本将打开 所有版本中的合同检查(用法 2)。因此你利用了 生成运行时的工具 你的条件和 为你执行合同继承。 你可以选择生产specic 参数的例外情况 验证,或具有默认值 ContractException。
我建议你在做出任何重大决定之前阅读整篇文章。
答案 2 :(得分:0)
这两种方法都很好。
用于检查前置条件的3种方式是
Contract.Requires - &gt;进入该方法后,特定条件必须为真。
Contract.Requires - &gt;与上述相同但如果条件不满足则抛出异常 需求始终是编译的,因此使用此方法需要对工具进行严格依赖。在使用此方法之前,您应该决定是否需要它。
您的第一种方法 - &gt;这种前提条件的好处是始终可以执行运行时检查。
在第一种方法中,您可能希望添加Contract.EndContractBlock();
我自己正在探索此功能,但我认为您可以在服务层中抛出异常并且没问题。
HTH