views:

1590

answers:

3

So here's a super simple interface for doing rest in WCF.

    [ServiceContract]
    public interface IRestTest
    {
        [OperationContract]
        [WebGet(UriTemplate="Operation/{value}")]
        System.IO.Stream Operation(string value);
    }

It works great, until i try to pass a string with periods in it, such as a DNS name... I get a 404 out of asp.net.

Changing the UriTemplate to stick parameters into the query string makes the problem go away. Anyone else see this or have a workaround?

A: 

That is true that a path part cannot contain a period or many other special characters for that matter. I experienced the same problem a while back and received an answer from TechNet team stating that querystring is your only option the could find. Sorry

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/d03c8331-1e98-4d5d-82a7-390942a93012/

bendewey
+1  A: 

I have a service with almost the exact signature. I can pass values that have a "." in the name. For example, this would work on mine:

[OperationContract]
[WebGet(UriTemplate = "category/{id}")]
string category(string id);

with the url http://localhost/MyService.svc/category/test.category I get the value `"test.category" passed in as the string value.

So there must be some other issue. how are you accessing the URL? just directly in the browser? Or via a javascript call? Just wondering if it is some error on the client side. The server passes the value just fine. I would recommending trying to access the url in your browser, and if it doesn't work then post exactly what URL you are using and what the error message was.

Also, are you using WCF 3.5 SP1 or just WCF 3.5? In the RESTFul .Net book I'm reading, I see there were some changes with regards to the UriTemplate.

And finally, I modified a simple Service from the RESTFul .Net book that works and I get the correct response.

class Program
{
    static void Main(string[] args)
    {
        var binding = new WebHttpBinding();
        var sh = new WebServiceHost(typeof(TestService));
        sh.AddServiceEndpoint(typeof(TestService),
            binding,
            "http://localhost:8889/TestHttp");
        sh.Open();
        Console.WriteLine("Simple HTTP Service Listening");
        Console.WriteLine("Press enter to stop service");
        Console.ReadLine();
    }
}

[ServiceContract]
public class TestService
{
    [OperationContract]
    [WebGet(UriTemplate = "category/{id}")]
    public string category(string id)
    {
        return "got '" + id + "'";
    }   
}
christophercotton
For kicks, i tried your interface in case it's related to the Stream type return, and i still get a 404 from asp.net for http://localhost/Software.svc/category/test.categoryIt's a URL that comes in via the address bar. If it comes to it, I'll cook up an IHttpModule that works around the bug.
John Ketchpaw
A: 

Here's an example HttpModule that fixes the 'period' when they occur in REST parameters. Note that I've only seen this happen in the Development Server (aka Cassini), in IIS7 it seems to work without this "hack". The example I've included below also replaces the file extension '.svc' which I adapted from this answer. How to remove thie “.svc” extension in RESTful WCF service?

public class RestModule : IHttpModule
{
    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest +=
            delegate
            {
                HttpContext ctx = HttpContext.Current;
                string path = ctx.Request.AppRelativeCurrentExecutionFilePath;

                int i = path.IndexOf('/', 2);
                if (i > 0)
                {
                    int j = path.IndexOf(".svc", 2);
                    if (j < 0)
                    {
                        RewritePath(ctx, path, i, ".svc");
                    }
                    else
                    {
                        RewritePath(ctx, path, j + 4, "");
                    }
                }
            };
    }

    private void RewritePath(HttpContext ctx, string path, int index, string suffix)
    {
        string svc = path.Substring(0, index) + suffix;
        string rest = path.Substring(index);
        if (!rest.EndsWith(ctx.Request.PathInfo))
        {
            rest += ctx.Request.PathInfo;
        }
        string qs = ctx.Request.QueryString.ToString();
        ctx.RewritePath(svc, rest, qs, false);
    }
}
CodeMonkeyKing