1
votes

I am trying to include the basic Breeze sample in a DotNetNuke module (it works fine in a standalone WebAPI project). To simplify things I remove the client and will just refer to the URL JSON calls I make in the Chrome browser.

I can see my metadata and a full list of items, eg: http://www.dnndev.me/DesktopModules/framework/api/breeze/dare/metadata http://www.dnndev.me/DesktopModules/framework/api/breeze/dare/todos

however, when I try to filter the list from the URL, it always returns the full list, e.g. http://www.dnndev.me/DesktopModules/framework/api/breeze/dare/todos?=DareId%20eq%204

I think it is something to do with the way I have declared the MapHTTRoute. The problem is that DotNetNuke modules do not have a Global.ascx. I have copied the BreezeWebApiconfig.cs file into my App_Start folder and this does fire when I debug, however DotNetNuke uses mechanism for registering routes:

using DotNetNuke.Web.Api;

namespace SmartThinker.Modules.Framework
{
    public class RouteMapper : IServiceRouteMapper
    {
        public void RegisterRoutes(IMapRoute mapRouteManager)
        {
            mapRouteManager.MapHttpRoute("framework", "BreezeApi", "breeze/{controller}/{action}", new[] { "SmartThinker.Modules.Framework.Controllers" });
        }
    }
}

I have read up on http://www.breezejs.com/documentation/web-api-controller#note01 and http://www.breezejs.com/documentation/web-api-routing but it seems that it's something to do with the way DNN registers the routes. Is there anyway to do this without using BreezeWebApiConfig.cs?

My controller code has the BreezeController attribute. (When I do connect the sample client to it I do get a list of items - it just does not filter, so I think it is something to with the OData Action filters. How can I debug where the problem is?

Update 1) Here is the metadata: http://www.ftter.com/desktopmodules/framework/api/dare/metadata

The GetUsers method: http://www.ftter.com/desktopmodules/framework/api/dare/getusers

and the GetUsers method trying to filter by UserID (which doesn't work, which is the issue) http://www.ftter.com/desktopmodules/framework/api/dare/getusers?=UserID%20eq%204 http://www.ftter.com/desktopmodules/framework/api/dare/GetUsersWithoutCors?=UserID%20eq%204 (this returns IQueryable)

Here is the controller:

[BreezeController]
public class DareController : DnnApiController
{
    private readonly EFContextProvider<FrameworkContext> contextProvider = new EFContextProvider<FrameworkContext>();

    [AllowAnonymous]
    [HttpGet]
    public HttpResponseMessage Metadata()
    {
        var response = Request.CreateResponse(HttpStatusCode.OK, contextProvider.Metadata());
        return GetResponseWithCorsHeader(response);
    }

    [AllowAnonymous]
    [HttpGet]
    public HttpResponseMessage GetUsers()
    {
        var userInfoController = new UserInfoController();

        var response = Request.CreateResponse(HttpStatusCode.OK, userInfoController.GetUsers());
        return GetResponseWithCorsHeader(response);
    }

    [AllowAnonymous]
    [HttpGet]
    public IQueryable<User> GetUsersWithoutCors()
    {
        return contextProvider.Context.Users;
    }
}
1

1 Answers

3
votes

The routing is not really a Breeze issue. How your server routes requests to your controller is up to you. What we do out-of-the-box is just one way among innumerable many.

You have the [BreezeController] attribute on your controller yes? Can you put a sample endpoint up where we could hit it. Might get some clues from that. Also post the controller. A tiny example should do ... something returning metadata and one method returning IQueryable.

Update 25 Jun 2013

I think you've discovered a bug in the way our [BreezeController] discovers methods returning IQueryable<T>.

The [BreezeController] attribute scans your Web API controller methods and (in effect) applies the [BreezeQueryable] attribute to methods returning IQueryable<T>.

[BreezeQueryable] is an extension of the Web API's [Queryable] that adds support for $select, $expand, and nested $orderby ... all missing from the current [Queryable].

I see now that your GetUsers() method returns HttpResponseMessage rather than IQueryable<User>. Let's assume that the userInfoController.GetUsers() method inside your method returns IQueryable<User>. Otherwise, the OData query parameters will not apply and we'll have to take this in a different direction. Moving along ...

I checked with v.1.3.6 of the Breeze.WebApi.dll and it does not detect that the HttpResponseMessage is wrapping IQueryable<T>. Therefore, it does not apply the client's OData query criteria (or any other OData modifiers for that matter). This shortcoming (in my opinion) is a bug. The following should be equivalent implementations:

[HttpGet]
public IQueryable<TodoItem> Todos() {
    return _repository.Todos;
}

[HttpGet]
public HttpResponseMessage TodosWrapped()
{
    return Request.CreateResponse(HttpStatusCode.OK, _repository.Todos);
}

The second, "wrapped" method does not respect the OData query parameters.

Fortunately, there is a workaround until we get this fixed. Just add the [BreezeQueryable] attribute explicitly ... as in:

[HttpGet]
[BreezeQueryable]
public HttpResponseMessage TodosWrapped()
{
    return Request.CreateResponse(HttpStatusCode.OK, _repository.Todos);
}

I confirmed that this approach does work.

Thanks for finding this.

Use OData query syntax

A colleague also noticed that your query URL does not use the OData query syntax. You wrote:

... /todos?=DareId%20eq%204

when it should be

... /todos/?$filter=DareId%20eq%204

Make sure you use ?$filter=