5

I'm implementing a custom WCF REST behavior, it implements/overrides the base WebHttpBehavior but allows for REST communication using a custom serializer. The code is based on Carlos' work here.

I've got it running but the thing is we REALLY want to use the UriTemplate functionality to allow for true REST-ful URIs. Has anyone seen this done or could provide help on finding the right implementation?

We're sticking with WCF on purpose to provide REST and SOAP endpoints at the same time so moving to Web API is not an option here.

Igor
  • 349
  • 1
  • 6
Brent Pabst
  • 1,156
  • 1
  • 15
  • 37
  • How are you hosting your WCF Service? What bindings are you using? – simon at rcl Jun 08 '14 at 16:33
  • We're hosting through IIS using Service Activation through code. We've got a custom REST and SOAP service host factory setup that lets us change behaviors, bindings, etc. and then use standard WCF Routing Service Activation to load each service using the REST and SOAP factories. – Brent Pabst Jun 09 '14 at 11:58
  • So what exactly is your problem? http://msdn.microsoft.com/en-us/library/bb675245%28v=vs.110%29.aspx – Paul Zahra Jun 09 '14 at 13:24
  • Hey @Paul, the issue is that I have no clue how to re-implement the UriTemplate functionality. We've overridden the base WebHttpBehavior to add additional functionality but this has caused us to lose the base functionality that includes the ability to do UriTemplate routing. If you check our Carlos' article I linked to he even stated they do not include it in the sample because it is so difficult. I'm looking for reference or samples of how to do it in our overridden methods/class. – Brent Pabst Jun 09 '14 at 13:50
  • 1
    @BrentPabst From Carlos' 'blog'... "In the new WCF Web API (you can preview the bits on the Codeplex site) implementing such a scenario is a lot simpler, and other features (such as UriTemplate) will just continue to work after the new formatter is plugged in."... have u read http://wcf.codeplex.com/discussions/255873 ? – Paul Zahra Jun 10 '14 at 08:54
  • Can't you just use Web API and get it to return JSON, xml etc ? – Paul Zahra Jun 10 '14 at 09:01
  • @PaulZahra As I mention in the OP no, we are using WCF on purpose. In addition the WCF Web API is the current ASP.NET Web API, just an earlier version so that doesn't help us out either. – Brent Pabst Jun 10 '14 at 15:01
  • Not sure, but maybe this answer would be helpfull: http://stackoverflow.com/questions/24014333/converting-wcf-soap-service-library-to-rest-service-library-for-mvc/24014861#24014861 – Ramunas Jun 12 '14 at 06:34
  • @Ramunas no unfortunately it doesn't help, that answer is a pretty basic example of wiring up SOAP and REST services. – Brent Pabst Jun 12 '14 at 18:17
  • Hi, I have the same problem, did you find a solution ? – vinhent Mar 13 '17 at 21:18

2 Answers2

0

I had started going down the road of implementing my own UriTemplate parsing/matching logic, but then I stumbled upon this answer (Using Custom WCF Body Deserialization without changing URI Template Deserialization) and found it did that and more.

In order to use it, you still have to uncomment the code related to validating that a UriTemplate is not used. I also ended up reformatting the code a bit for my purposes (taking out logic to check if there was more than one parameter, since in my use case the body would always be exactly one parameter).

Community
  • 1
  • 1
Dan Field
  • 20,885
  • 5
  • 55
  • 71
-1

The problem may just be that the example is slightly outdated. Also, the implementation class, NewtonsoftJsonBehavior, is explicitly overriding and throwing an InvalidOperationException within the Validate(ServiceEndpoint endpoint) method.

Using Carlos' example, remove the validation:

public override void Validate(ServiceEndpoint endpoint)
{
    base.Validate(endpoint);

    //TODO: Stop throwing exception for default behavior.
    //BindingElementCollection elements = endpoint.Binding.CreateBindingElements();
    //WebMessageEncodingBindingElement webEncoder = elements.Find<WebMessageEncodingBindingElement>();
    //if (webEncoder == null)
    //{
    //    throw new InvalidOperationException("This behavior must be used in an endpoint with the WebHttpBinding (or a custom binding with the WebMessageEncodingBindingElement).");
    //}

    //foreach (OperationDescription operation in endpoint.Contract.Operations)
    //{
    //    this.ValidateOperation(operation);
    //}
}

Add a UriTemplate to GetPerson or other method:

[WebGet, OperationContract]
Person GetPerson();

[WebGet(UriTemplate="GetPersonByName?l={lastName}"), OperationContract(Name="GetPersonByName")]
Person GetPerson(string lastName);

Within the Service class, add a simple implementation to validate that the arguments are parsed:

public Person GetPerson(string lastName)
{
    return new Person
    {
        FirstName = "First",
        LastName = lastName, // Return the argument.
        BirthDate = new DateTime(1993, 4, 17, 2, 51, 37, 47, DateTimeKind.Local),
        Id = 0,
        Pets = new List<Pet>
        {
            new Pet { Name= "Generic Pet 1", Color = "Beige", Id = 0, Markings = "Some markings" },
            new Pet { Name= "Generic Pet 2", Color = "Gold", Id = 0, Markings = "Other markings" },
        },
    };
}

In the Program.Main() method, a call to this new URL will parse and return my query string value without any custom implementation:

[Request]
SendRequest(baseAddress + "/json/GetPersonByName?l=smith", "GET", null, null);

[Response]
{
"FirstName": "First",
"LastName": "smith",
"BirthDate": "1993-04-17T02:51:37.047-04:00",
"Pets": [
{...},
{...}
}
Igor
  • 349
  • 1
  • 6
Keith
  • 100
  • 1