【问题标题】:MVC requests interfering with calls to AutoQuery-enabled ServiceStack APIMVC 请求干扰对启用 AutoQuery 的 ServiceStack API 的调用
【发布时间】:2015-12-10 15:22:17
【问题描述】:

我有一个 MVC 解决方案,其中包含一个 ServiceStack API 以及一个调用 API 服务的 MVC UI。其中一些服务是 AutoQuery GET 端点,我遇到了一个问题,即 ServiceStack 服务会在我调用服务时获取已发布的表单值或不相关的查询字符串值并引发参数错误。

我尝试了多种调用服务的方法:

using (var fooSvc = new HostContext.ResolveService<FooService>(HttpContext))
{
    var foos = (QueryResponse<Foo>)fooSvc.Get(new Foos());
    // Do stuff here
}

没有骰子。发布的表单值搞砸了,我在我的服务中收到System.FormatExceptionInput string was not in a correct format

var q = AutoQuery.CreateQuery(request, Request.GetRequestParams());

所以我尝试了:

var foos = (QueryResponse<Foo>)HostContext.ServiceController.Execute(new Foos());

在这种情况下,我收到 System.NotImplementedException 说它找不到 Post(Foos)Any(Foos)(有问题的电话是 GET)。

我确定我只是遗漏了一些东西。 Mythz,又有救我了吗?

编辑:我手动输入了该代码...最初的块有AutoQuery,而我的意思是QueryResponse...

编辑 2:这是我的 AutoQuery 服务的一般结构。这些都是服务上的GET,因为这些端点还需要支持POST 才能创建资源。例如,我的 URI 可能位于 http:/service.com/api/users,并且希望能够使用 AutoQuery 或 POST 使用 GET 来创建新用户。

[Authenticate]
public class UsersService : Service
{
    public IAutoQuery AutoQuery { get; set; }

    public object Get(Users request)
    {
        var q = AutoQuery.CreateQuery(request, Request.GetRequestParams());

        // Here I add some other conditions to the query object to filter results based on the user's role, etc.

        return AutoQuery.Execute(request, q);
    }

    [RequiredRole("Admin")]
    public object Post(CreateUser request)
    {
        var user = request.ConvertTo<User>();
        Db.Save(user);

        return user;
    }
}

【问题讨论】:

    标签: c# asp.net-mvc servicestack


    【解决方案1】:

    当您调用服务时,您只是直接在目标实例上调用方法。该方法返回什么?不太可能是 AutoQuery&lt;Foo&gt;,因为它不是 ServiceStack 中的有效类型:

    var foos = (AutoQuery<Foo>)fooSvc.Get(new Foos());
    

    如果您收到 FormatException,请检查导致它的 QueryString 参数。 Request 中的某些内容与 AutoQuery 字段不兼容。

    您是否自己创建了该方法,因为 AutoQuery 使用Any 方法生成服务,以便可以由任何动词调用。如果是自定义服务,请将其更改为 Any

    否则,您可以使用当前 HTTP 请求执行该方法:

    var foos = (QueryResponse<Foo>)HostContext.ServiceController
        .Execute(new Foos(), HttpContext.ToRequest());
    

    您还可以覆盖执行的动词:

    var req = HttpContext.ToRequest();
    req.Items[Keywords.InvokeVerb] = "GET";
    var foos = (QueryResponse<Foo>)HostContext.ServiceController
        .Execute(new Foos(), req);
    

    Custom AutoQuery Implementation

    如果您在尝试转发请求时有冲突的字段,我只会将它们更改为使用与 AutoQuery 请求不冲突的字段。但如果您仍想继续使用冲突字段,您可以创建一个 Custom AutoQuery Implementation 将其从 AutoQuery 服务中删除,例如:

    public class UsersService : Service
    {
        public IAutoQuery AutoQuery { get; set; }
    
        public object Any(Users request)
        {
            Dictionary<string, string> args = Request.GetRequestParams();
            args.Remove("OrganizationId");// E.g remove conflicted fields
    
            var q = AutoQuery.CreateQuery(request, args);
            return AutoQuery.Execute(request, q);
        }
    }
    

    【讨论】:

    • 修复了错误。我的意思是输入QueryResponse 而不是AutoQuery。关于 AutoQuery 设置,我自己创建了它。添加了一些示例。我没有遵循推荐的设置吗?
    • 我用你的代码覆盖了动词,但我最终得到了同样的FormatException 错误。场景是这样的:它是一个创建记录的表单。我有该表单的视图模型,其中包含创建记录所需的字段以及一些 SelectList 对象以填充下拉列表。如果出现验证错误,我会重新填充这些 SelectList,以便我可以返回视图并且用户可以解决问题。问题是表单已发布到控制器,当我为SelectLists 提取数据时,表单值都是请求的一部分。
    • @Josh AutoQuery 通过查看 QueryString/FormData 以及类型化的 DTO 来工作,这就是它仍然可以使用空 DTO 的原因。您可能与发布到控制器的 QueryString/FormData 发生冲突,该控制器正被转发到 AutoQuery 以执行。调查 FormatException 的 StackTrace 以查看它是否提供任何关于哪个参数存在冲突的提示。
    • 我的视图模型有一个名为OrganizationId 的字段可以为空。如果我发布一个空选择,我会收到该错误。但重要的是要注意,我不希望该表单字段成为 AutoQuery 的一部分...我真的希望能够在此调用我的 GET 没有任何 AutoQuery 内容特殊情况,但我仍然需要在该端点上为我的 API 消费者支持 AutoQuery。
    • 您正在从 MVC 控制器中对 MVC HTTP 请求进行一些奇怪的转发,您只希望应用部分 HTTP 请求 - 这 IMO 很丑陋,并且由于您使用的是预期的问题冲突的领域。除了传入一个模拟 IRequest(例如 BasicRequest)来控制 AutoQuery 请求看到的 Params 之外,不要使用 AutoQuery,只需使用带有类型 DTO 的显式服务,而不查看 QueryString。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 2014-01-03
    • 2017-09-20
    相关资源
    最近更新 更多