C# OData GetKeyFromUri - Resource not found for the segment 'odata'












0














I've updated from Microsoft.AspNet.OData version 6.0.0 to OData version 7.0.1. The upgrade has broken my ability to get the Id from a path when linking one object to another. Here is my Web API call to add a role to a specific user using the OData standard:



POST: http://localhost:61506/odata/users('bob')/roles/$ref
Request body: {"@odata.id":"http://localhost:61506/odata/roles(1)"}


The Web API method verifies the user and then makes a call to Helpers.GetKeyFromUri to get the role Id value from the request body.



[HttpPost, HttpPut]
public IHttpActionResult CreateRef([FromODataUri] string key, string navigationProperty, [FromBody] Uri link)
{
// Ensure the User exists
User user = new User().GetById(key);
if (user == null)
{
return NotFound();
}

// Determine which navigation property to use
switch (navigationProperty)
{
case "roles":
// Get the Role id
int roleId;
try
{
roleId = Helpers.GetKeyFromUri<int>(Request, link);
}
catch (Exception ex)
{
return BadRequest();
}

// Ensure the Role exists
Role role = new Role().GetById(roleId);
if (role == null)
{
return NotFound();
}

// Add the User/Role relationship
user.Roles.Add(role);
user.Update();

break;

default:
return StatusCode(HttpStatusCode.NotImplemented);
}

return StatusCode(HttpStatusCode.NoContent);
}


That function looks like this (Originally from here but with updated references: https://github.com/OData/ODataSamples/blob/master/RESTier/Trippin/Trippin/Helpers.cs)



using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Routing;
using Microsoft.AspNet.OData.Extensions;
using Microsoft.AspNet.OData.Routing;
using Microsoft.OData.UriParser;

namespace Project1.Extensions
{
public class Helpers
{
public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}

var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);

var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler));

string serviceRoot = urlHelper.CreateODataLink(
request.ODataProperties().RouteName,
pathHandler, new List<ODataPathSegment>());
var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());

var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
if (keySegment == null)
{
throw new InvalidOperationException("The link does not contain a key.");
}

var value = keySegment.Keys.FirstOrDefault().Value;
return (TKey)value;
}
}
}


This line of code is now throwing the following error: Resource not found for the segment 'odata'



var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());


This worked fine when using OData 6.0.0 but fails in 7.0.1. It seems to have some sort of issue parsing my odata segment or not being able to find it at all. Here is my routing setup if it helps:



public static void Register(HttpConfiguration config)
{
// Setup the OData routes and endpoints
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "odata",
model: GetEdmModel());

// Enable OData URL querying globally
config.Count().Filter().Select().OrderBy().Expand().MaxTop(null);
}









share|improve this question



























    0














    I've updated from Microsoft.AspNet.OData version 6.0.0 to OData version 7.0.1. The upgrade has broken my ability to get the Id from a path when linking one object to another. Here is my Web API call to add a role to a specific user using the OData standard:



    POST: http://localhost:61506/odata/users('bob')/roles/$ref
    Request body: {"@odata.id":"http://localhost:61506/odata/roles(1)"}


    The Web API method verifies the user and then makes a call to Helpers.GetKeyFromUri to get the role Id value from the request body.



    [HttpPost, HttpPut]
    public IHttpActionResult CreateRef([FromODataUri] string key, string navigationProperty, [FromBody] Uri link)
    {
    // Ensure the User exists
    User user = new User().GetById(key);
    if (user == null)
    {
    return NotFound();
    }

    // Determine which navigation property to use
    switch (navigationProperty)
    {
    case "roles":
    // Get the Role id
    int roleId;
    try
    {
    roleId = Helpers.GetKeyFromUri<int>(Request, link);
    }
    catch (Exception ex)
    {
    return BadRequest();
    }

    // Ensure the Role exists
    Role role = new Role().GetById(roleId);
    if (role == null)
    {
    return NotFound();
    }

    // Add the User/Role relationship
    user.Roles.Add(role);
    user.Update();

    break;

    default:
    return StatusCode(HttpStatusCode.NotImplemented);
    }

    return StatusCode(HttpStatusCode.NoContent);
    }


    That function looks like this (Originally from here but with updated references: https://github.com/OData/ODataSamples/blob/master/RESTier/Trippin/Trippin/Helpers.cs)



    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Web.Http.Routing;
    using Microsoft.AspNet.OData.Extensions;
    using Microsoft.AspNet.OData.Routing;
    using Microsoft.OData.UriParser;

    namespace Project1.Extensions
    {
    public class Helpers
    {
    public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
    {
    if (uri == null)
    {
    throw new ArgumentNullException("uri");
    }

    var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);

    var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler));

    string serviceRoot = urlHelper.CreateODataLink(
    request.ODataProperties().RouteName,
    pathHandler, new List<ODataPathSegment>());
    var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());

    var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
    if (keySegment == null)
    {
    throw new InvalidOperationException("The link does not contain a key.");
    }

    var value = keySegment.Keys.FirstOrDefault().Value;
    return (TKey)value;
    }
    }
    }


    This line of code is now throwing the following error: Resource not found for the segment 'odata'



    var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());


    This worked fine when using OData 6.0.0 but fails in 7.0.1. It seems to have some sort of issue parsing my odata segment or not being able to find it at all. Here is my routing setup if it helps:



    public static void Register(HttpConfiguration config)
    {
    // Setup the OData routes and endpoints
    config.MapODataServiceRoute(
    routeName: "ODataRoute",
    routePrefix: "odata",
    model: GetEdmModel());

    // Enable OData URL querying globally
    config.Count().Filter().Select().OrderBy().Expand().MaxTop(null);
    }









    share|improve this question

























      0












      0








      0







      I've updated from Microsoft.AspNet.OData version 6.0.0 to OData version 7.0.1. The upgrade has broken my ability to get the Id from a path when linking one object to another. Here is my Web API call to add a role to a specific user using the OData standard:



      POST: http://localhost:61506/odata/users('bob')/roles/$ref
      Request body: {"@odata.id":"http://localhost:61506/odata/roles(1)"}


      The Web API method verifies the user and then makes a call to Helpers.GetKeyFromUri to get the role Id value from the request body.



      [HttpPost, HttpPut]
      public IHttpActionResult CreateRef([FromODataUri] string key, string navigationProperty, [FromBody] Uri link)
      {
      // Ensure the User exists
      User user = new User().GetById(key);
      if (user == null)
      {
      return NotFound();
      }

      // Determine which navigation property to use
      switch (navigationProperty)
      {
      case "roles":
      // Get the Role id
      int roleId;
      try
      {
      roleId = Helpers.GetKeyFromUri<int>(Request, link);
      }
      catch (Exception ex)
      {
      return BadRequest();
      }

      // Ensure the Role exists
      Role role = new Role().GetById(roleId);
      if (role == null)
      {
      return NotFound();
      }

      // Add the User/Role relationship
      user.Roles.Add(role);
      user.Update();

      break;

      default:
      return StatusCode(HttpStatusCode.NotImplemented);
      }

      return StatusCode(HttpStatusCode.NoContent);
      }


      That function looks like this (Originally from here but with updated references: https://github.com/OData/ODataSamples/blob/master/RESTier/Trippin/Trippin/Helpers.cs)



      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net.Http;
      using System.Web.Http.Routing;
      using Microsoft.AspNet.OData.Extensions;
      using Microsoft.AspNet.OData.Routing;
      using Microsoft.OData.UriParser;

      namespace Project1.Extensions
      {
      public class Helpers
      {
      public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
      {
      if (uri == null)
      {
      throw new ArgumentNullException("uri");
      }

      var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);

      var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler));

      string serviceRoot = urlHelper.CreateODataLink(
      request.ODataProperties().RouteName,
      pathHandler, new List<ODataPathSegment>());
      var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());

      var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
      if (keySegment == null)
      {
      throw new InvalidOperationException("The link does not contain a key.");
      }

      var value = keySegment.Keys.FirstOrDefault().Value;
      return (TKey)value;
      }
      }
      }


      This line of code is now throwing the following error: Resource not found for the segment 'odata'



      var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());


      This worked fine when using OData 6.0.0 but fails in 7.0.1. It seems to have some sort of issue parsing my odata segment or not being able to find it at all. Here is my routing setup if it helps:



      public static void Register(HttpConfiguration config)
      {
      // Setup the OData routes and endpoints
      config.MapODataServiceRoute(
      routeName: "ODataRoute",
      routePrefix: "odata",
      model: GetEdmModel());

      // Enable OData URL querying globally
      config.Count().Filter().Select().OrderBy().Expand().MaxTop(null);
      }









      share|improve this question













      I've updated from Microsoft.AspNet.OData version 6.0.0 to OData version 7.0.1. The upgrade has broken my ability to get the Id from a path when linking one object to another. Here is my Web API call to add a role to a specific user using the OData standard:



      POST: http://localhost:61506/odata/users('bob')/roles/$ref
      Request body: {"@odata.id":"http://localhost:61506/odata/roles(1)"}


      The Web API method verifies the user and then makes a call to Helpers.GetKeyFromUri to get the role Id value from the request body.



      [HttpPost, HttpPut]
      public IHttpActionResult CreateRef([FromODataUri] string key, string navigationProperty, [FromBody] Uri link)
      {
      // Ensure the User exists
      User user = new User().GetById(key);
      if (user == null)
      {
      return NotFound();
      }

      // Determine which navigation property to use
      switch (navigationProperty)
      {
      case "roles":
      // Get the Role id
      int roleId;
      try
      {
      roleId = Helpers.GetKeyFromUri<int>(Request, link);
      }
      catch (Exception ex)
      {
      return BadRequest();
      }

      // Ensure the Role exists
      Role role = new Role().GetById(roleId);
      if (role == null)
      {
      return NotFound();
      }

      // Add the User/Role relationship
      user.Roles.Add(role);
      user.Update();

      break;

      default:
      return StatusCode(HttpStatusCode.NotImplemented);
      }

      return StatusCode(HttpStatusCode.NoContent);
      }


      That function looks like this (Originally from here but with updated references: https://github.com/OData/ODataSamples/blob/master/RESTier/Trippin/Trippin/Helpers.cs)



      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net.Http;
      using System.Web.Http.Routing;
      using Microsoft.AspNet.OData.Extensions;
      using Microsoft.AspNet.OData.Routing;
      using Microsoft.OData.UriParser;

      namespace Project1.Extensions
      {
      public class Helpers
      {
      public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri)
      {
      if (uri == null)
      {
      throw new ArgumentNullException("uri");
      }

      var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);

      var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler));

      string serviceRoot = urlHelper.CreateODataLink(
      request.ODataProperties().RouteName,
      pathHandler, new List<ODataPathSegment>());
      var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());

      var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault();
      if (keySegment == null)
      {
      throw new InvalidOperationException("The link does not contain a key.");
      }

      var value = keySegment.Keys.FirstOrDefault().Value;
      return (TKey)value;
      }
      }
      }


      This line of code is now throwing the following error: Resource not found for the segment 'odata'



      var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer());


      This worked fine when using OData 6.0.0 but fails in 7.0.1. It seems to have some sort of issue parsing my odata segment or not being able to find it at all. Here is my routing setup if it helps:



      public static void Register(HttpConfiguration config)
      {
      // Setup the OData routes and endpoints
      config.MapODataServiceRoute(
      routeName: "ODataRoute",
      routePrefix: "odata",
      model: GetEdmModel());

      // Enable OData URL querying globally
      config.Count().Filter().Select().OrderBy().Expand().MaxTop(null);
      }






      odata






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 10 at 18:03









      user1624184

      427




      427
























          1 Answer
          1






          active

          oldest

          votes


















          -1














          I caused myself the same problem by changing routePrefix from null to odata just like you've done. Setting routePrefix to null will allow your code to work perfectly fine as long as you don't need a route prefix (such as /odata/).






          share|improve this answer










          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.


















          • This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
            – Simonare
            14 hours ago










          • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
            – Ian Lim
            6 hours ago











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53241904%2fc-sharp-odata-getkeyfromuri-resource-not-found-for-the-segment-odata%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          -1














          I caused myself the same problem by changing routePrefix from null to odata just like you've done. Setting routePrefix to null will allow your code to work perfectly fine as long as you don't need a route prefix (such as /odata/).






          share|improve this answer










          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.


















          • This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
            – Simonare
            14 hours ago










          • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
            – Ian Lim
            6 hours ago
















          -1














          I caused myself the same problem by changing routePrefix from null to odata just like you've done. Setting routePrefix to null will allow your code to work perfectly fine as long as you don't need a route prefix (such as /odata/).






          share|improve this answer










          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.


















          • This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
            – Simonare
            14 hours ago










          • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
            – Ian Lim
            6 hours ago














          -1












          -1








          -1






          I caused myself the same problem by changing routePrefix from null to odata just like you've done. Setting routePrefix to null will allow your code to work perfectly fine as long as you don't need a route prefix (such as /odata/).






          share|improve this answer










          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          I caused myself the same problem by changing routePrefix from null to odata just like you've done. Setting routePrefix to null will allow your code to work perfectly fine as long as you don't need a route prefix (such as /odata/).







          share|improve this answer










          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          share|improve this answer



          share|improve this answer








          edited 5 hours ago









          Joe McMahon

          2,3021226




          2,3021226






          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          answered 14 hours ago









          Jonathan Pickard

          1




          1




          New contributor




          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.





          New contributor





          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          Jonathan Pickard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.












          • This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
            – Simonare
            14 hours ago










          • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
            – Ian Lim
            6 hours ago


















          • This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
            – Simonare
            14 hours ago










          • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
            – Ian Lim
            6 hours ago
















          This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
          – Simonare
          14 hours ago




          This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. - From Review
          – Simonare
          14 hours ago












          This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
          – Ian Lim
          6 hours ago




          This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
          – Ian Lim
          6 hours ago


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53241904%2fc-sharp-odata-getkeyfromuri-resource-not-found-for-the-segment-odata%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Xamarin.form Move up view when keyboard appear

          Post-Redirect-Get with Spring WebFlux and Thymeleaf

          Anylogic : not able to use stopDelay()