简体   繁体   English

为什么我的ServiceStack服务会抛出异常?

[英]Why does my ServiceStack service throw an exception?

I have constructed a simple Rest service using ServiceStack (which is brilliant), that returns a list of key value pairs. 我使用ServiceStack构建了一个简单的Rest服务(很棒),它返回一个键值对列表。

My service looks like this: 我的服务如下:

 public class ServiceListAll : RestServiceBase<ListAllResponse>
{
    public override object OnGet(ListAllResponse request)
    {          
        APIClient c = VenueServiceHelper.CheckAndGetClient(request.APIKey, VenueServiceHelper.Methods.ListDestinations);

        if (c == null)
        {
            return null;
        }
        else
        {
            if ((RequestContext.AbsoluteUri.Contains("counties")))
            {
                return General.GetListOfCounties();
            }

            else if ((RequestContext.AbsoluteUri.Contains("destinations")))
            {
                return General.GetListOfDestinations();
            }

            else
            {
                return null;
            }
        }
    }
}

my response looks like this: 我的回答如下:

    public class ListAllResponse
{
    public string County { get; set; }
    public string Destination { get; set; }
    public string APIKey { get; set; }     
}

and I have mapped the rest URL as follows: 我已经映射了其余的URL,如下所示:

.Add<ListAllResponse>("/destinations")
.Add<ListAllResponse>("/counties")

when calling the service 在调用服务时

http://localhost:5000/counties/?apikey=xxx&format=xml HTTP://本地主机:5000 /县/ apikey = XXX&格式= XML

I receive this exception (a breakpoint in the first line of the service is not hit): 我收到此异常(服务的第一行中的断点未被命中):

NullReferenceException Object reference not set to an instance of an object. NullReferenceException未将对象引用设置为对象的实例。 at ServiceStack.Text.XmlSerializer.SerializeToStream(Object obj, Stream stream) at ServiceStack.Common.Web.HttpResponseFilter.<GetStreamSerializer>b_ 3(IRequestContext r, Object o, Stream s) at ServiceStack.Common.Web.HttpResponseFilter.<>c _DisplayClass1.<GetResponseSerializer>b__0(IRequestContext httpReq, Object dto, IHttpResponse httpRes) at ServiceStack.WebHost.Endpoints.Extensions.HttpResponseExtensions.WriteToResponse(IHttpResponse response, Object result, ResponseSerializerDelegate defaultAction, IRequestContext serializerCtx, Byte[] bodyPrefix, Byte[] bodySuffix) at ServiceStack.Text.XmlSerializer.SerializeToStream(Object obj,Stream stream)at ServiceStack.Common.Web.HttpResponseFilter。<GetStreamSerializer> b_ 3(IRequestContext r,Object o,Stream s)at ServiceStack.Common.Web.HttpResponseFilter。<>在ServiceStack.WebHost.Endpoints.Extensions.HttpResponseExtensions.WriteToResponse(IHttpResponse响应,对象结果,ResponseSerializerDelegate defaultAction,IRequestContext serializerCtx,Byte [] bodyPrefix,Byte []中的c _DisplayClass1。<GetResponseSerializer> b__0(IRequestContext httpReq,Object dto,IHttpResponse httpRes) bodySuffix)

The exception is thrown regardless of whether I include any parameters in call or not. 无论我是否在调用中包含任何参数,都会抛出异常。 I have also created a number of other services along the same lines in the same project which work fine. 我也在同一个项目的同一行创建了许多其他服务,工作正常。 Can anyone point me in the right direction as to what this means? 任何人都可以指出我的方向是正确的吗?

Your web service design is a little backwards, Your Request DTO should go on RestServiceBase<TRequest> not your response. 您的Web服务设计有点倒退,您的请求DTO应该继续使用RestServiceBase<TRequest>而不是您的响应。 And if you're creating a REST-ful service I recommend the name (ie Request DTO) of your service to be a noun, eg in this case maybe Codes. 如果您正在创建REST-ful服务,我建议您将服务的名称(即Request DTO)作为名词,例如在这种情况下可能是代码。

Also I recommend having and using the same strong-typed Response for your service with the name following the convention of '{RequestDto}Response', eg CodesResponse. 此外,我建议使用与“{RequestDto} Response”约定相同的名称对服务使用相同的强类型响应,例如CodesResponse。

Finally return an empty response instead of null so clients need only handle an empty result set not a null response. 最后返回一个空响应而不是null,因此客户端只需处理空结果集而不是空响应。

Here's how I would re-write your service: 以下是我将如何重写您的服务:

 [RestService("/codes/{Type}")]
 public class Codes {
      public string APIKey { get; set; }     
      public string Type { get; set; }
 }

 public class CodesResponse {
      public CodesResponse() {
           Results = new List<string>();
      }

      public List<string> Results { get; set; }
 }

 public class CodesService : RestServiceBase<Codes>
 {
      public override object OnGet(Codes request)
      {          
           APIClient c = VenueServiceHelper.CheckAndGetClient(request.APIKey, 
              VenueServiceHelper.Methods.ListDestinations);

           var response = new CodesResponse();
           if (c == null) return response;

           if (request.Type == "counties") 
                response.Results = General.GetListOfCounties();
           else if (request.Type == "destinations") 
                response.Results = General.GetListOfDestinations();

           return response; 
     }
 }

You can either use the [RestService] attribute or the following route (which does the same thing): 您可以使用[RestService]属性或以下路由(执行相同的操作):

Routes.Add<Codes>("/codes/{Type}");

Which will allow you to call the service like so: 这将允许您像这样调用服务:

http://localhost:5000/codes/counties?apikey=xxx&format=xml

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM