ServiceStack AutoQuery,隐式/显式查询

时间:2014-11-03 21:04:18

标签: servicestack ormlite-servicestack

我有以下请求DTO:

[Route("/processresults")]
public class FindProcessResults : QueryBase<ProcessResult, ProcessResultDto>  {}

ProcessResult有一个名为Id(Int32)的属性。我的数据库中有两个ProcessResults,Id 1和2。

当我对/ processresults执行GET时?Id = 1我返回了一个ProcessResult。大。

然而,当我发布这个JSON时,我得到两个ProcessResults返回。查询未执行。当我将属性Id添加到FindProcessResults时,JSON调用确实有效,但是我没有将EnableUntypedQueries设置为false。

PostData: {"Id":"1"}

这可能是什么问题?

奖励积分,如果我使用表单数据制作POST,我会收到以下异常:

{
   ResponseStatus: {
     ErrorCode: "RequestBindingException",
     Message: "Unable to bind request",
     StackTrace: " at ServiceStack.Host.RestHandler.CreateRequest(IRequest httpReq, IRestPath restPath)\ \ at ServiceStack.Host.RestHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName)"
   }
}

但是,如果我使用x-www-form-urlencoded执行相同的操作(帖子),则查询将按预期工作(返回单个结果)。

结论:虽然我可以通过将我希望通过(Id)查询的参数添加到类型化请求来解决此问题,但这违背了我想要实现的目的,这是我的数据存储的通用查询机制。 GET版本的请求已经存在该功能。

我相信它与AutoQueryServiceBase的实现有关:

        public virtual object Exec<From>(IQuery<From> dto)
        {
            SqlExpression<From> q;
            using (Profiler.Current.Step("AutoQuery.CreateQuery"))
            {
                q = AutoQuery.CreateQuery(dto, Request.GetRequestParams());
            }
            using (Profiler.Current.Step("AutoQuery.Execute"))
            {
                return AutoQuery.Execute(dto, q);
            }
        }

这是使用Request.GetRequestParams(),它将从查询字符串或表单参数返回参数,而JSON请求正在尝试反序列化为<From> dtoFrom类型FindProcessResults没有Id属性,因此未填充并传递给查询。

请求的HTTP请求/响应:

请求

POST /processresults HTTP/1.1
Host: localocl
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 36d4b37e-0407-a9b3-f2f2-5b024d7faf7f

{"Id":1}

响应

Cache-Control → private
Content-Length → 1580
Content-Type → application/json; charset=utf-8
Date → Mon, 03 Nov 2014 21:20:43 GMT
Server → Microsoft-IIS/8.5
Vary → Accept
X-AspNet-Version → 4.0.30319
X-Powered-By → ServiceStack/4.033 Win32NT/.NET, ASP.NET

{"Offset":0,"Total":2,"Results"....

1 个答案:

答案 0 :(得分:0)

您应该强烈考虑使用GET请求来使用AutoQuery服务,这些服务更适合使用HTTP Verb,它也更易于缓存和内省。

如果您想POST并且不想使用HTML表单POST(即x-www-form-urlencoded内容类型),则需要通过将参数添加到请求来形式化参数DTO:

[Route("/processresults")]
public class FindProcessResults : QueryBase<ProcessResult, ProcessResultDto>  
{
    public int Id { get; set; }
}

否则,它会尝试将JSON反序列化为空DTO,其中忽略任何不存在的属性。