是否可以将简单的Request数据绑定到NancyFX中的方法调用?

时间:2013-04-03 11:24:16

标签: nancy

我正在向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     
}

2 个答案:

答案 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>