tags:

views:

418

answers:

5

I'm still learning about REST and, in my test, came up with this scenario I don't know how to deal with.

I have an existing sample WCF service which uses Linq-to-Sql. Its a tremendously simple database with a single table called "Tasks" which has four fields: Id, Description, IsCompleted, and EnteredDate. (I mentioned this because I have no data contracts defined in the service itself, it all comes from the Context created by Linq.)

Getting data was trivial to convert to REST... as was deleting data. However, inserting new records doesn't seem as easy.

My RPC-style contract operation looks like this:

    [OperationContract]
    void AddTask(string description);

The Id, IsCompleted, and EnteredDate are not needed as the service implementation looks like this:

    public void AddTask(string description)
    {
        TaskListLinqDataContext db = new TaskListLinqDataContext();
        Task task = new Task() 
           { Description = description, IsCompleted = false, 
             EntryDate = DateTime.Now };

        db.Tasks.InsertOnSubmit(task);
        db.SubmitChanges();
    }

The Id is an Identity and therefore handled by the database.

My first thought was to decorate the Operation contract like this:

    [WebInvoke(Method="PUT", UriTemplate="tasks/{description}")]
    [OperationContract]
    void AddTask(string description);

But I don't really know how to get this to work. When I try using Fiddler to add this it returns a result of 411 (Length Required).

What would be the proper way to do this? Will I have to re-write the implementation to accept a whole XML document representing the new record?

A: 

I think this pretty much describes how to add an item to a container in a restful way.

Tom
@thaggie: the attached link tells me that my UriTemplate and operation are probably valid, but doesn't help me solve my problem. I don't know how to get the data to the service properly. For example, what kind of a Request Builder would Fiddler use to get the data into the service?
Sailing Judo
A: 

Depending on the requirements, you could simply enable regular CRUD via Astoria? I have a series covering how to do this with LINQ-to-SQL here. Just a thought.

Marc Gravell
This is interesting because I hadn't seen ADO.NET Data Services in action yet. However, it seems like more work that what i was looking for. It seems like I should be able to make what I have work somehow, or possibly change the signature some.
Sailing Judo
A: 

If you want to do a RESTful web service then don't use a WCF application. Modify your URI template to something like Task/new and put the data of the new task in the body of the POST http request. I implement RESTful web services in ASP.NET as generic handlers (*.ashx). This allow me to ready the http method and go from there.

kevin

+1  A: 

Take a look at the WCF REST Starter Kit, which can be downloaded from CodePlex here.

Lee Harold
+3  A: 

Results:

I finally found a nice blog post that helped me resolve this. It turns out I was pretty much doing things correctly but I was putting the test into Fiddler improperly. I also added a few more details to my attribute.

[WebInvoke(RequestFormat = WebMessageFormat.Xml, 
           ResponseFormat = WebMessageFormat.Xml,
           Method = "POST", UriTemplate = "tasks/{description}", 
           BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
void AddTask(string description);

When I put my Uri into Fiddler it needed to look like this:

http://ipv4.fiddler:8054/tasks/this+is+a+sample+desc+that+works

Now my service correctly accepts the data and can add the task to the database.

Sailing Judo