How can I manually execute Breeze filters in Web Api?

大城市里の小女人 提交于 2019-12-19 04:06:45

问题


I want to use some external server-side logic to modify properties on the results of a query. To do this, I'll need to apply the Breeze query options, modify the result set, and return it.

I know essentially how I can apply OdataQueryOptions to my query, but I don't want to miss out on all the things that BreezeJS does that Web Api's OData doesn't. For example, I want to keep inlineCount.

How can I do this? Is there some way to hook into Breeze's query modifying code?

In case it matters, I'm using Entity Framework 6 and Web Api 2.


回答1:


Ok, I'm not sure if there's a better way (because this seems like a lot of work for what seems like it would be a common use case), but here's how I solved this.

I inherited from the QueryHelper class to modify the PostExecuteQuery method to execute a delegate.

public class ExtendedQueryHelper : QueryHelper
{
    public ExtendedQueryHelperOptions Options { get; set; }

    public ExtendedQueryHelper(ODataQuerySettings querySettings) : base(querySettings)
    {}

    public override IEnumerable PostExecuteQuery(IEnumerable queryResult)
    {
        if (Options != null && Options.PostExecuteQueryHandler != null)
        {
            return Options.PostExecuteQueryHandler(queryResult);
        }

        return base.PostExecuteQuery(queryResult);
    }
}

The delegate is defined in a class called ExtendedQueryHelperOptions

public class ExtendedQueryHelperOptions
{
    private const string EXTENDED_QUERY_HELPER_OPTIONS_KEY = "EXTENDED_QUERY_HELPER_OPTIONS_KEY";
    public delegate IEnumerable PostExecuteQueryDelegate(IEnumerable queryResult);

    public PostExecuteQueryDelegate PostExecuteQueryHandler { get; set; }

    public void InjectIntoRequest(HttpRequestMessage request)
    {
        request.Properties.Add(EXTENDED_QUERY_HELPER_OPTIONS_KEY, this);
    }

    public static ExtendedQueryHelperOptions GetFromRequest(HttpRequestMessage request)
    {
        object options;
        request.Properties.TryGetValue(EXTENDED_QUERY_HELPER_OPTIONS_KEY, out options);

        return (ExtendedQueryHelperOptions)options;
    }
}

In order to set these options, I had to inherit from BreezeQueryableAttribute and inject these options when the QueryHelper is being created:

public class ExtendedBreezeQueryableAttribute : BreezeQueryableAttribute
{
    protected HttpRequestMessage Request { get; set; }

    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        Request = actionContext.Request;
        base.OnActionExecuting(actionContext);
    }

    protected override QueryHelper NewQueryHelper()
    {
        var queryHelper = new ExtendedQueryHelper(GetODataQuerySettings());
        queryHelper.Options = ExtendedQueryHelperOptions.GetFromRequest(Request);

        return queryHelper;
    }
}

Now I can inject code to be run on the filtered results like this:

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

    [HttpGet]
    [ExtendedBreezeQueryable]
    public IQueryable<Foo> Foos()
    {
        var options = new ExtendedQueryHelperOptions
        {
            PostExecuteQueryHandler = delegate(IEnumerable results) {
                // This code will be run after the querying has been
                // applied by Breeze
                var foos = results.Cast<Foo>().ToList();

                foreach (var foo in foos)
                {
                    foo.ComputedProperty = ComputeSomething();
                }

                return foos;
            }
        };

        // Inject these options into the Request, so the ExtendedBreezeQueryableAttribute
        // can get to them later
        options.InjectIntoRequest(Request);
        return Db.Foos;
    }
}



回答2:


I looked at the answer here and struggled with it, so came up with something simpler (but possibly far inferior).

Assuming you want to modify the entities which Breeze's query returns, then put a .ToList() on the end of the query, modify the list items, and return them with 'list.AsQueryable()' Like this:

public IQueryable<CameraMetaData> CameraMetaDatas()
{

    var query = ContextProvider.Context.Cameras;
    var list = query.ToList();

    foreach(var l in  list)
    {
        //modify values
    }
    return list.AsQueryable();
}


来源:https://stackoverflow.com/questions/23794343/how-can-i-manually-execute-breeze-filters-in-web-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!