Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L2Q with Web API and EF: IQueryable interpreted as Dictionary #11

Closed
manzanotti opened this issue Sep 27, 2013 · 3 comments
Closed

L2Q with Web API and EF: IQueryable interpreted as Dictionary #11

manzanotti opened this issue Sep 27, 2013 · 3 comments

Comments

@manzanotti
Copy link

This is admittedly my first attempt to use L2Q, but I am getting an unfathomable error!

I am using Web Api (1.0) and Entity Framework (5.something).

I have a relatively simple object:

public class AgentTask
{
    public int Id { get; set; }
    public Guid AgentId { get; set; }
    public Guid PropertyId { get; set; }
    public TaskType Type { get; set; }
    public TaskStatus Status { get; set; }
    public Guid CreatedBy { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? SlaDeadline { get; set; }
    public DateTime? UpdatedDate { get; set; }
    public virtual Property Property { get; set; }
}

In my DbContext, I have a set of these:

public IDbSet<AgentTask> AgentTasks { get; set; }

I have a service layer that runs a simple query against this set:

public IQueryable<TaskViewModel> GetIncompleteTasks(Guid agentGuid)
{
    var tasks = _commonDatabaseContext.AgentTasks
        .Include(t => t.Property)
        .Where(
            t =>
                t.AgentId == agentGuid &&
                (!t.Property.IsRemoved.HasValue || (t.Property.IsRemoved.HasValue && !t.Property.IsRemoved.Value)) &&
                (t.Status != TaskStatus.Completed && t.Status != TaskStatus.Suspended && t.Status != TaskStatus.Deleted))
        .Select(a => new TaskViewModel()
        {
            Address = a.Property.Line1 + "," + a.Property.Line2,
            Description = a.Type,
            Id = a.Id,
            PropertyId = a.PropertyId,
            SlaDeadline = a.SlaDeadline,
            UpdatedDate = a.UpdatedDate
        });

    return tasks;
}

And this is called by my controller method:

[HttpGet]
[LinqToQueryable]
public IQueryable<TaskViewModel> GetIncompleteTasks()
{
    var loggedUser = _authenticator.GetUserId();

    if (loggedUser != null)
    {
        var result = _agentTaskListService.GetIncompleteTasks(loggedUser.Value);

        return result.AsQueryable();
    }

    throw new ArgumentException("Not Found");
}

I am calling my controller using a jQuery Ajax GET request. The url ends:

GetIncompleteTasks?$top=10&$skip=0&orderby=slaDeadline%20desc&$inlinecount=allpages

I get the following exception:

{
    "message": "An error has occurred.",
    "exceptionMessage": "The action 'GetIncompleteTasks' on controller 'AgentListing' with return type 'System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' cannot support querying. Ensure the type of the returned content is IEnumerable, IQueryable, or a generic form of either interface.",
    "exceptionType": "System.InvalidOperationException",
    "stackTrace": "   at System.Web.Http.QueryableAttribute.ValidateReturnType(Type responseContentType, HttpActionDescriptor actionDescriptor)\r\n   at System.Web.Http.QueryableAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecuted(HttpActionContext actionContext, HttpResponseMessage response, Exception exception)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<>c__DisplayClass2.<System.Web.Http.Filters.IActionFilter.ExecuteActionFilterAsync>b__0(HttpResponseMessage response)\r\n   at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass41`2.<Then>b__40(Task`1 t)\r\n   at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)"
}

I can put a breakpoint on the line return result.AsQueryable(); in the controller method, and it hits it fine.

Any suggestions as to what I've done wrong?

@beyond-code-github
Copy link
Owner

Hey thanks for the extra info. From the stack trace it looks like the Web API Queryable attribute/message handler is getting invoked somewhere along the line... is it possible that you've got this set up as a global filter in Webapiconfig.cs?

Basically this is the web api odata handler... so it's trying to process a response that has already been processed by linq to querystring and hence throwing an error.

Pete

@manzanotti
Copy link
Author

Yep, that was the problem alright! Cheers for working that out. :)

@beyond-code-github
Copy link
Owner

No worries, enjoy Linq to Querystring!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants