2

I have a Web Api 2 server, an Entity Framework data layer, and a BreezeJS client. I have some extra properties that aren't mapped to the database that I want to set at query time. Something like:

public class Foo
{
    // Various mapped properties
    // ...

    // These properties are not mapped, and I want
    // to set them on the returned data depending
    // on the current user's roles/authorization
    public bool CanEdit { get; set; }
    public bool CanDelete { get; set; }
}

[BreezeController]
public class BreezeController : BaseController
{
    // ...

    [HttpGet]
    public IQueryable<Foos> Users()
    {
        // How can I set the CanEdit and CanDelete properties
        // here (and only on the data as filtered by the OData
        // queries)?
        return Db.Foos; // Db.Foos is a DbSet<Foo>
    }
}

Is there any way to do this?

Note: The logic to determine CanEdit/CanDelete will be too complex to be encompassed in a LINQ to Entities query.

Eric
  • 5,842
  • 7
  • 42
  • 71
  • Is there any reason it has to be IQueryable? Why can't you return IEnumerable? If you really want an IQueryable returned, you could run the query, then set those properties on the returned data, and return `.AsQueryable()` – mnsr May 21 '14 at 04:58
  • How are the values of those properties determined? – jmcilhinney May 21 '14 at 04:59
  • Sorry @malik, I just realized how generic the question sounded based on the title. I fixed the title to reflect that I want this needs to work on an OData query in a Web API – Eric May 21 '14 at 05:00
  • @jmcilhinney, Will it suffice to say the logic may be complex and wouldn't be able to be converted to a SQL query by LINQ to Entities? – Eric May 21 '14 at 05:01
  • @Eric you can't pass non-mapped (complex) properties to Linq to Entities. You could do something like this: `if (CanEdit) { Db.Foos.Where(w => w.Whatever); }` – mnsr May 21 '14 at 05:05
  • I just found this question, which seems like it might be an option for doing what I need. I'll report back after I get a chance to give it a try. http://stackoverflow.com/a/15495804/546561 – Eric May 21 '14 at 05:17
  • No that wouldn't suffice. What I'm thinking is that you may be able to make them read-only properties and have their values calculated internally rather than set from outside. – jmcilhinney May 21 '14 at 06:06
  • @jmcilhinney, gotcha. The logic will depend on the logged in user, which the Model has no knowledge of. – Eric May 21 '14 at 12:42
  • It doesn't really seem appropriate that those be properties of an entity then. A view model, yes, but an entity, no. Your controller should be mapping your entity to a view model and setting those properties as an extension to that mapping process. – jmcilhinney May 21 '14 at 12:57
  • @jmcilhinney, you're right. I'll need to change that. I still have the problem of setting those after the filtered Odata query has been applied, and unless there's a better way, I'll probably have to manually apply the Odata filters as in the question I linked. – Eric May 21 '14 at 13:01

2 Answers2

0

I ended up solving this by deriving from QueryHelper and hooking into PostExecuteQuery(). See my answer here.

Community
  • 1
  • 1
Eric
  • 5,842
  • 7
  • 42
  • 71
0

In terms of OData, there are 2 concepts that are applicable to your case.

First one is open type, which allows you to add undefined properties to entity. You can refer this blog How to Use Open Type in OData for more information. And latest WebApi OData has supported open complex type.

Second one is custom annotation, which can be used to define additional information associated with your entity. In your case, you can write "@Foo.CanEdit:true" into the entity payload to tell the client that your Foo entity is editable. Same for "CanDelete".

I can provide more info about open type and custom annotation if you like to know more.

zoe
  • 849
  • 6
  • 7