我正在向Nancy模块发送一些简单的用户详细信息。我正在利用Nancy的模型绑定功能从请求中收集用户详细信息并将其传递给我的UserService.Add(...)
方法,如下所示:
南希模块
Post["/add"] = parameters =>
{
var user = this.Bind<UserDetails>();
UserService.Add(user);
return HttpStatusCode.OK;
};
用户详细信息类
public class UserDetails
{
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
用户服务
public static void Add(UserDetails user)
{
//Add the user
}
这适用于南希模块中的简洁语法。但是,这意味着我被迫创建一个数据传输(DTO)类,只是为了获取Request有效载荷。
是否有可能完全避免这个中间阶层?而不是将类绑定到有效负载,是否可以绑定Method参数?
这会给代码看起来像这样:
南希模块
Post["/add"] = parameters =>
{
this.BindAndCall<UserService>("Add");
return HttpStatusCode.OK;
};
用户服务
public static void Add(string firstName, string lastName, string email, string userName, string password)
{
//Add the user
}
答案 0 :(得分:3)
您总是可以创建一些扩展方法或自定义绑定器,但是您将服务的内部实现与有效负载的参数的确切命名相结合,这是不好的,因为稍后当您的服务发生变化时,您需要改变有效载荷或跳槽。 DTO没有任何问题,无需创建。
答案 1 :(得分:3)
参数标签 - DTO增殖的部分解决方案
在我看来,DTO很痛苦,因为它们往往会扩散到阴影领域。当您决定重新组织服务层时,这会产生令人头疼的问题。
那么为什么不使用dynamic
类型并忘记DTO和强类型路由参数呢?动态值非常方便,但它们有自己的问题,主要是你不能将它们传递给扩展方法。因此,正确呈现路线参数更容易,因此模型绑定,因此DTO,因此意大利面条和傻帽子。
所以这里的部分解决方案依赖于Nancy的模型绑定。它显着减少了路线级别的仪式,并有助于遏制恼人的DTO扩散。
南希基础模块
public class _BaseModule : NancyModule
{
public class ParameterBag
{
// All the params used across all routes, GET and POST
public string UserName { get { return this.Value; } }
public string UserIds { get; set; }
public string UserId { get; set; }
public string Value { get; set; }
public int Skip { get; set; }
public int Take { get; set; }
}
public ParameterBag Params;
public _BaseModule(): this(""){}
public _BaseModule(string modulePath): base(modulePath)
{
Before += ctx =>
{
this.Params = this.Bind<ParameterBag>();
return null;
};
}
}
ParameterBag
类包含我感兴趣的所有参数 所有路径。由于Nancy只会在有效负载中找到匹配字段时填充属性,因此您可以根据需要为此类添加任意数量的属性,而无需关心它们是否将由给定路由使用。
请注意绑定是如何在Before
挂钩中进行的。这意味着每个路由(派生自_BaseModule
)将自动将任何匹配的参数值绑定到通用ParameterBag
类属性。无需特定的路线级干预。
这样做的效果是为路由处理程序提供可以使用的强类型参数值。
南希模块
public class UserModule : _BaseModule
{
public UserModule()
{
// handlers go here
}
}
路线处理程序示例
Get["/user/{userid}/username/available"] = _ =>
{
return Response.AsJson(new
{
// the username is a hidden value
// the userid comes from the url
value = Params.UserName,
valid = UserService.UserNameAvailable(Params.UserName, Params.UserId)
}
);
};
使用示例
以下示例依赖于jqBootstrapValidation。它显示了Binding技巧如何用于作为ajax有效负载的一部分提供的URL 和上提供的参数数据(请参阅value属性)。
<input
type="text"
id="username"
name="username"
placeholder="User Name"
data-validation-ajax-ajax="/user/@user.id/username/available"
data-validation-ajax-message="This name has already been taken"
value="@user.UserName"
required>