5
votes

How can I control the base URL attribute in the root element of an OData service document?

I'm setting up an OData service using WebApi, the System.Web.Http.OData.Builder.ODataConventionModelBuilder and controllers inheriting from System.Web.Http.OData.ODataController

It all works beautifully and Excel 2013 happily accesses the data.

The problem arises when trying to use Excel 2010 and PowerPivot. I'm aware of the fix for JSON formatted responses being sent in the absence of an Accept header, but I can't find any discussion of problems with the base URL.

I have set up my odata route with config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel()); and when I hit this URL I get a response of <service xml:base="http://localhost/odata" xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom"/>

Excel 2010 + PowerPivot reads this URL and decides that because there is no trailing slash on the base URI, it should request collections with URIs in the root, e.g. http://localhost/Products instead of http://localhost/odata/Products as it should.

I have confirmed my suspicion by accessing a static version of the service document, modified to add the trailing slash to the base attribute value and the correct URL is then requested for the collection resource.

I've tried working through the ASP.Net WebStack source code to see if I can override a formatter or something, but got lost. Any suggestions would be greatly appreciated.

1
Did you ever solve this or just moved to excel 2013? – Nikolaj
I ended up with a hack by adding a DelegatingHandler which checks if the RequestURI is for the OData model and if it does, uses a RegEx to find the base URL and append the trailing slash. Horrible, but it works. – Darran

1 Answers

3
votes

I had the same problem with PowerPivot and I managed to fix the xml:base to be compatible with it. Here's the part of the code needed:

class MyODataPathHandler : DefaultODataPathHandler
{
    public override string Link(ODataPath path)
    {
        if (path.PathTemplate == "~")
        {
            return path.ToString() + "/";
        }
        return base.Link(path);
    }
}

and

config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel(), new MyODataPathHandler(), ODataRoutingConventions.CreateDefault());

the custom ODataPathHandler will add the extra slash for the default path, which results in an xml:base that works around the bug in PowerPivot. The second issue is PowerPivot expects data in XML, not in JSON. One workaround for that can be found at http://aspnetwebstack.codeplex.com/workitem/820