4

I am trying to wire up TFS 2012 event notifications to ServiceStack, but I just keep getting the error:

{
    "responseStatus": {
        "errorCode": "RequestBindingException",
        "message": "Unable to bind request",
        "stackTrace": "at ServiceStack.WebHost.Endpoints.RestHandler.GetRequest(IHttpRequest httpReq, IRestPath restPath)\r\n   
                       at ServiceStack.WebHost.Endpoints.RestHandler.ProcessRequest (IHttpRequest httpReq, IHttpResponse httpRes, String operationName)"
    }
}

Here is my DTO (It contains some bits that I have tried to make it work).

[Route("/releasemanagement/tfsevents/buildcomplete", "POST")]
[DataContract(Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public class TfsEventBuildComplete : IReturn<BuildCompleteResponse>
{
    [DataMember]
    public string BuildUri { get; set; }

    [DataMember]
    public string TeamFoundationServerUrl { get; set; }

    [DataMember]
    public string TeamProject { get; set; }

    [DataMember]
    public string Title { get; set; }

    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public TfsEventStatusChange StatusChange { get; set; }

    [DataMember]
    public string ChangedBy { get; set; }
}

public class TfsEventStatusChange
{
    public string FieldName { get; set; }

    public string NewValue { get; set; }
}

Here is the XML that comes from TFS:

<BuildStatusChangeEvent xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <BuildUri>vstfs:///Build/Build/4799</BuildUri>
    <TeamFoundationServerUrl>http://TFSURL:8080/tfs/collection</TeamFoundationServerUrl>
    <TeamProject>iSAMS</TeamProject>
    <Title>iSAMS Build Release_20130814.1 Quality Changed To Publish</Title>
    <Subscriber>[02]\Project Collection Service Accounts</Subscriber>
    <Id>Release_20130814.1</Id>
    <Url>http://TFSURL:8080/tfs/web/build.aspx?pcguid=GUID&amp;builduri=vstfs:///Build/Build/4799</Url>
    <TimeZone>GMT Daylight Time</TimeZone>
    <TimeZoneOffset>+01:00:00</TimeZoneOffset>
    <ChangedTime>8/14/2013 9:33:30 AM</ChangedTime>
    <StatusChange>
        <FieldName>Quality</FieldName>
        <NewValue>Publish</NewValue>
    </StatusChange>
    <ChangedBy>DOMAIN\USER</ChangedBy>
</BuildStatusChangeEvent>

I think ServiceStack is effectively failing to deserialise the request due to the namespacing, but I can't figure it out.

Most of what I have tried has come from here:

XML deserializing only works with namespace in xml

Community
  • 1
  • 1
gregpakes
  • 4,465
  • 29
  • 43
  • Did you try `[DataContract(Namespace="")]` like in the [answer](http://stackoverflow.com/a/9691240/795339) to the related post you linked to? Note that your XML sample doesn't have `xmlns="..."` but `xmlns:xsd=...` and `xmlns:xsi=...`. I believe that can make a significant difference. – Mike Mertsock Aug 14 '13 at 13:25
  • Yes - I did try that. The question I cited is the other way round to what I want. So I first tried an empty namespace, then tried to mimic what is in the XML (what is in the example). – gregpakes Aug 14 '13 at 13:39

1 Answers1

5

Here's what I did to get the sample request XML to work:

  1. Set the Name property of your DataContract attribute to BuildStatusChangeEvent. This controls the expected name of the top-level XML element. Otherwise ServiceStack will expect the XML to look like <TfsEventBuildComplete><BuildUri>...
  2. Set the Namespace property of your DataContract attribute to an empty string, so that no specific xmlns attributes are required in the request
  3. Set the Order property of your DataMember attributes to specify the order in which the XML elements are sorted in the XML you are getting from TFS. By default, the XML serializer will expect the elements to be sorted alphabetically, so you must override this or some portion of your properties won't get deserialized correctly
[Route("/releasemanagement/tfsevents/buildcomplete", "POST")]
[DataContract(Namespace = "", Name = "BuildStatusChangeEvent")]
public class TfsEventBuildComplete : IReturn<BuildCompleteResponse>
{
    [DataMember(Order=1)]
    public string BuildUri { get; set; }

    [DataMember(Order=2)]
    public string TeamFoundationServerUrl { get; set; }

    [DataMember(Order=3)]
    public string TeamProject { get; set; }

    [DataMember(Order=4)]
    public string Title { get; set; }

    [DataMember(Order=5)]
    public string Id { get; set; }

    [DataMember(Order=6)]
    public TfsEventStatusChange StatusChange { get; set; }

    [DataMember(Order=7)]
    public string ChangedBy { get; set; }
}
Community
  • 1
  • 1
Mike Mertsock
  • 11,825
  • 7
  • 42
  • 75