How to Link to OData Collection in Razor using ASP

2019-06-19 17:09发布

I have an ASP.NET MVC 4 app that i'm incorporating an OData API into. This is running the 2012.2 stuff with the larger OData support.

I did not use a separate area for this...that might have been a mistake but my app is small and area seemed overkill.

I've got my controllers setup correctly and an example path to my Segments collection (segments is a type in my domain) is "/odata/Segments". This loads as expected and is working.

On my homepage i'm trying to add a link to this resource using Razor's Html.ActionLink (or RouteLink) but it seems the OData controllers layout doesn't quite work with those methods because the controllers are prefixed with "odata" when registered in WebAPIConfig:

config.Routes.MapODataRoute("OData Route", "odata", model );

I can trick the method to construct the correct url by pretending there's an odata controller when there certainly isn't one (as far as i know) with something like this:

@Html.RouteLink("Segments", "Segments", "odata")

but that seems like a hack.

I don't quite understand the ASP.NET routing plumbing well enough to understand how that prefix passed to MapODataRoute is being incorporated into the MVC chain so that i can use the "right" razor method the "right" way.

just for kicks, here's my SegmentsController:

public class SegmentsController : EntitySetController<Segment, long>
{

    private MarketerDB db = new MarketerDB();

    // GET api/segments
    override public IQueryable<Segment> Get()
    {
        return db.Segments.AsQueryable();
    }


    protected override Segment GetEntityByKey(long key)
    {
        return db.Segments.Find(key);
    }


    public IQueryable<Affiliate> GetAffiliates([FromODataUri] long key)
    {
        return this.GetEntityByKey(key).Affiliates.AsQueryable();
    }

    protected override void Dispose(bool disposing)
    {
        db.Dispose();
        base.Dispose(disposing);
    }
}

1条回答
兄弟一词,经得起流年.
2楼-- · 2019-06-19 17:51

We have an ODataLink method on System.Web.Http.UrlHelper but we forgot to add one to the MVC System.Web.Mvc.UrlHelper. Till we add it, you can use this extension method,

namespace System.Web.Mvc
{
    public static class UrlHelperExtensions
    {
        private static IODataPathHandler _pathHandler = new DefaultODataPathHandler();

        public static string ODataUrl(this UrlHelper urlHelper, string routeName, params ODataPathSegment[] segments)
        {
            string odataPath = _pathHandler.Link(new ODataPath(segments));
            return urlHelper.HttpRouteUrl(
                routeName,
                new RouteValueDictionary() { { ODataRouteConstants.ODataPath, odataPath } });
        }
    }
}

and call it from your razor views by doing something like (assuming there is an entityset customers and you want to put the navigation link to orders on customers(42)),

@Url.ODataUrl("odata", new EntitySetPathSegment("customers"), new KeyValuePathSegment("42"), new NavigationPathSegment("orders"))

Make sure you have an @using System.Web.Http.OData.Routing directive in your razor view.

查看更多
登录 后发表回答