hi, it's long time after.netcore 1.0 released , and the odata lib 7.0 is ready, and the 6.0 is already released, but the odata web api vnext is doing nothing. can you make a plan then i know when can i update my project .
and , the odata lib 7.0 can't install for vs2107, and the vnext branch is import 6.x version, can you update it?
thank you
xiaoxin
Hi @xiaoxin1983, thank you for bringing up the topics. Please be assured that we are actively working on the next version of OData WebAPI to be compatible with ASP.NET Core. We recently had some shuffling so this is why it seemed like vNext is inactive during the past months. Please note that the vNext branch is still in its early stages and we may take a different approach once we have our architecture finalized. I'm unable to give any firm timelines for releases at the moment, but I would say at least 2-3 months out.
For OData lib 7.0, we don't have a plan to port to VS2017 just yet, but we do have visibility on the request for it. We are working on moving OData lib 7.0 to .NET Standard, and we'll coordinate moving WebAPI to 7.0 at that point.
Thank you for your patience and contributions to the community!
@AlanWong-MS
Thank you for your reply ! we think the .netcore/aspnetcore is exciting, so we are actively upgrading to new platform, but we stop at odata, i tried to debugging and compile the vnext branch. here is some issues , FYI
may you publish a smallest available version as soon as you can ?
Thank you !
We are working with the ASP.NET team here to make sure we have the correct implementations since there are fundamental changes in the ASP.NET Core framework--we are still in the discussion/design process. Thank you for informing us of the issues that you've found in the current state of vNext branch. We'll provide code updates to the repo once we're signed off and will address the bugs that you mentioned. :)
Pinging @xuzhg to see if he has any quick input on your questions with the current implementation of vNext in the meantime.
thank you very much for your supports đŻ , i'm Looking forward to the new version
+100, can't wait for OData running on ASP.NET Core :) Thanks to the team for working on this, please let us know even if there's an super early Alpha we can start using/testing and provide feedback to you guys..!
@lelong37 it's possible to get it working with minor modifications to the source code. The problems I faced mostly related to gluing the request to populate the appropriate odata class. I've seen some forks achieving that and I have a local modification that I used myself that seem to get the job done. It's not pretty, but if you need something, it's more than doable.
@AlanWong-MS I would like to see more modular components in the redesign. Maybe some sort of provider that I can inject, so that I can manually map from request to the output, if I don't want to rely on MVC routing, or plug in MVC routing partially where it makes sense. Also, I would like to be able to mix OData and GraphQL overtop of webapi. detect which query language the client is asking for, and pipe accordingly, without having to create separate urls for each language. I think it's important to support multiple query languages, and make generic abstractions where it makes sense. Would something like that be practical with the redesign?
@wizarrc thanks for sharing your experience, can you be more specific on what your fix looks like?
@mrns sure, I can see if I can do an actual fork and link to it here if you'd like. It might take me a week to get around to it. I'm not really a nuget author, so right now I have everything stored locally. I made a few common sense fixes like changing the output filters to async for things like count to work better with EF core. Other fixes were hacky to get it to flow though; can't remember off the top of my head (3+ months ago). There are other forks and examples I built from. I'd recommend you check them out.
@wizarrc cool thanks! no need to create a nuget package if that's complicated, maybe a github repo? I am actually having issues setting up vNext in my webapi project because although it is a .net core web api, I have some dependencies with net452 so I had to set it as my target framework and it seems vnext is not compatible. Looking at vNext code and sample right now to see if I can make any changes to make it work.
By the way, do you use the convention model builder to hook up an existing EF data model? Like this, where Customer and Order are autogenerated classes:
```c#
public static IEdmModel GetConventionModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet
builder.EntitySet
return builder.GetEdmModel();
}
```
@wizarrc, I was able to make it work by compiling Microsoft.AspNetCore.OData targeted to net452. I have setup an EdmModel based on my own POCO classes and I can see the odata/$metadata endpoint just fine with all the odata model information ;)
The problem I am facing now is that eventhough I've added [EnableQuery] to the controller I get 404 when trying to issue a get to a url similar to odata/Products(1), although my the same controller is reachable at product/1. I already tried a few combinations as well, like odata/Product(1) and so on with no luck. Any ideas? This is how I am enabling the OData route:
```c#
app.UseMvc(builder => builder.MapODataRoute("odata", model));
```
Does it mean we ain't gonna get OData Webapi previews before Asp.net Core 2.0 released?
Could anybody from MS let us know the status on OData please?
@wizarrc, sorry I somehow missed your message from earlier:
@AlanWong-MS I would like to see more modular components in the redesign. Maybe some sort of provider that I can inject, so that I can manually map from request to the output, if I don't want to rely on MVC routing, or plug in MVC routing partially where it makes sense. Also, I would like to be able to mix OData and GraphQL overtop of webapi. detect which query language the client is asking for, and pipe accordingly, without having to create separate urls for each language. I think it's important to support multiple query languages, and make generic abstractions where it makes sense. Would something like that be practical with the redesign?
We're still in the middle of refactoring the project as our resources were being pulled left and right during the past months. Could you please file a feature request for this so that it doesn't lose visibility? Thanks!
@anton-abyzov, we're in the middle of some housecleaning tasks to enable faster releases and more effective community contributions. We made a lot of progress on the WebAPI refactor and we're doing our best to make it compatible with .NET Framework to reduce as much pain as possible. We're wrapping up on the .NET Framework portion and will start on the .NET Core portion shortly. We'll have to revisit the ASP.NET Core 2.0 use case and determine whether it's the right version for us (and you :) ). For now, the status for the project is "in progress;" unfortunately, I don't think we'll be pushing out a preview before ASP.NET Core 2.0 is released. Hope that helps a bit!
While the complete support would be the most awaited piece of the work, please consider there are many classes that should not live in the same context of the asp.net / webapi stuff. This is what I mean:
Please move these pieces out here in a neststandard library. This should never require any dependency from the asp.net stuff.
.NET Core 2.0 , AspNetCore 2.0 , EFCore 2.0 all published , and odata core ?
This is the last thing I am waiting on now in order to move to .NET Core. With the release of .NET Core 2.0 less than a day ago, what's the update on OData support?
+1
Hi everyone,
I'm as excited for the newly released .NET Core/Standard 2.0 as everyone. :)
Short answer: we've been focused on cleaning the repo for easier understanding and code changes. We're going into our planning phase now and will visit the .NET Core 2.0 topic as we're working on the next version of WebAPI OData. At this moment, there's no definitive answer to when we're moving to .NET Core 2.0, but with our repo improvements during these past months and release of VS2017.3, on your personal environment, you _should_ be able to attempt the migration to .NET Standard/Core 2.0 with a few clicks.
Long answer: as you may know, OData is on .NET Standard 1.1, which supports .NET Core 1.0; .NET Standard 2.0 is needed for .NET Core 2.0. During the past months, we've made a lot of improvements to the layout of our repos and internal test systems to help devs modify the code faster and easier. One of those things that we've changed is creating a separate solution (in VS2017!) to house the .NET Standard version of OData and associated unit tests in .NET Core. With the release of VS2017.3, one should be able to open that solution file and switch to .NET Standard 2.0 and .NET Core 2.0 with a few clicks in the project settings within VS2017.
We don't have an answer as to when we're moving to .NET Core 2.0 yet as we need to scope out how big of a change it is to move to .NET Standard 2.0 and how big of an impact it will be to the rest of the OData users. This discussion will take place during the oncoming weeks, but for now, one can try out OData on .NET Standard 2.0 and .NET Core 2.0 locally with the steps mentioned above.
Hope that helps and thanks for your continued interest and support!
It is great to see there is some progress, but can you please direct me to somewhere, anywhere that gives some direction on how we can add an odata service to a >net Core 2 WebAPI solution?
The documentation is all over the place, and the documentation that is there is a fork with dead links. There are a lot of people who have committed to the oData interface and we really need a workable, comprehensible path to getting a service running on our webapi core2
Hi! Thanks to everyone for their patience. Yes, we will be releasing a version of OData WebApi that supports ASP.Net Core. We hope to have an alpha on NuGet in the next several weeks. After that, weâd like to get feedback before releasing an RTM version. If you are interested in help out, please let us know.
The current plan involves breaking changes. We want to release the ASP.Net Core version in a Microsoft namespace as opposed to the current System namespace. We decided to change the existing System namespace to a Microsoft namespace while leaving the existing APIs signature as-is. This does constitute a breaking change, albeit one we think is easy to accommodate. Weâd love to get your feedback on this approach and its impact to you. If you have a different idea or just want to chime in with a pro or con, please let us know.
At a high level, the plan is to combine the code from the master branch (formerly OData60) and the maintenance-aspnetcore branch (formerly vNext) to create two version of OData WebApi from a common codebase: a ASP.Net WebApi 2 compatible version and an ASP.Net Core compatible version. Below, youâll find some details on how we arrived at this plan. We plan to add a feature branch to the OData\WebApi repository and begin consolidating the changes there.
Feel free to chime in with thoughts and concerns regarding this plan on either this issue or a new GitHub issue. Again, thanks for your patience. â The OData Team.
We have examined the code in both the master branch (formerly OData60) and the maintenance-aspnetcore branch (formerly vNext) and created a design that supports both ASP.Net WebApi 2 and ASP.Net Core from a single code base. We found that the two branches share about 80% commonality and that the ASP.Net WebApi classes were intertwined with much of the common code. The design we landed on was to refactor the existing code into an ASP.Net WebApi 2-specific portion, which is tightly coupled to the ASP.Net WebApi 2-specific classes, and a common portion which has no dependency on ASP.Net. The code from maintenance-aspnetcore can then be refactored to consume the common portion and provide the ASP.Net Core-specific portion.
This design will allow us to ship both an ASP.Net WebApi 2 compatible version of OData WebApi, a.k.a. the recently release OData WebApi 6.0, for customers not interested in migrating to .Net core and an ASP.Net Core compatible version of OData WebApi for customers that do plan to migrate or build new services on ASP.Net Core. The common parts of the code can be maintained more easily for both versions which reduces the overall engineering maintenance cost. Additionally, we will be able to add new features to the ASP.Net WebApi 2 version, as well as the new ASP.Net Core version.
The design has been prototyped and mostly coded so weâre confident in the design. The next step is to begin reviewing and committing the code to refactor the existing library into two components. This will be created through a series of pull requests targeting a new feature branch. Once committed, weâll create and publish a nightly Nuget package in MyGet.org for testing. From there, weâll add the ASP.Net Core version and tests and publish a second nightly Nuget package in MyGet.org. The feature branch will ultimately be merged to master and weâll ship both packages via Nuget.org.
One issue we ran into during prototyping was the best way to structure the common code. We considered packing the common code into a new Dll based on .NetStandard which can run on Net Framework 4.x as well as .Net Core. However, some of the APIs we needed would have caused a dependency on .NetStandard 1.5, which would force a dependency on .Net Framework 4.6.1 instead of 4.5. To avoid this, we decided to use a Shared Project, a VS 2015 feature that allows common code to be maintained in a single project and included in additional projects. As a result, weâre able to allow each version of the library to take a dependency on the appropriate version of .Net, which will require that the common code compiles for both frameworks and will likely use some conditional compilation, i.e. #if.
An additional issue is that we want to release the ASP.Net Core version in a Microsoft namespace as opposed to the current System namespace. The compiler does not offer a way to compile the same code in two namespaces and we didnât like the idea of conditional compilation for the namespace. We decided to change the existing System namespace to a Microsoft namespace while leaving the existing APIs signature as-is. We have validated that only changing the using statements in the End to End tests results in a project that compiles and runs. This does constitute a breaking change, albeit one we think is easy to accommodate. Weâd love to get your feedback on this approach and its impact to you. If you have a different idea or just want to chime in with a pro or con, please let us know.
The last hurdle we faced was a build system that can build and release the ASP.Net Core version of OData WebApi. .Net Core is only officially supported on VS2017 so weâll need to not only require VS2017 for development but also lab builds that produce our Nuget packages. Weâve spent the last few months upgrading our engineering system to eliminate this hurdle. The first part of the refactor will target VS2015; VS2017 will be added as we introduce the ASP.Net Core portion.
About shared project, I'd recommend using multi-target feature of new csproj format of vs 2017. It allows you to multi target as following for example: net45;netcoreapp20. After that, you can reference dlls, add files etc based on condition. For example, take a look at what I've done in one of my projects:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netcoreapp2.0</TargetFrameworks> <!-- Multi target library -->
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
<!-- Please add following file in .NET 4.5 target -->
<Compile Remove="Implementations\ActiveDirectoryUserServiceProvider.cs" />
</ItemGroup>
<ItemGroup>
<!-- Please add nuget packages to all targets -->
<PackageReference Include="AntiXSS" Version="4.3.0" />
<PackageReference Include="IdentityServer3" Version="2.6.1" />
</ItemGroup>
<ItemGroup>
<!-- Please add following project to all targets -->
<ProjectReference Include="..\Bit.Owin\Bit.Owin.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<!-- Please add following dll in .NET 4.5 target -->
<Reference Include="System.DirectoryServices.AccountManagement" />
</ItemGroup>
</Project>
@ysmoradi - I looked at the multi-target but there is a subtle difference between this and a shared project: a shared project does not produce an assembly. At the moment, we don't have a plan to refactor the shared into assemblies but there is a feature ask for it. I do think the multi-target makes sense if we want to breakout common code into reusable bits.
@robward-ms Based on current core-fx team approach which results into several "binaries/nuget packages" such as System.Linq.dll & System.Linq.Expressions.dll etc, I think it would be nice to see a common approach across all "Microsoft/.NET community" based products.
Consider a scenario when there is a library developer who wants to create some nuget package for OData server side to provide some added value to the community, what nuget package should be referenced when there is no "ASP.NET/ASP.NET Core" thing required in that library? There are two libraries based on your current decision, "MS.AspNet.OData" & "MS.AspNetCore.OData", so what should be done in this situation?
@ysmoradi - We have a request for splitting parts of WebApi into ODL, #1054. Our thinking at the moment is that this makes sense for certain parts that are not strictly part of the server side, such as model building. That would mean that MS.AspNet.OData" & "MS.AspNetCore.OData would contain the server-side components. In your example, OData.Core would be the thing to reference.
FYI, there is an answer on #1066 which discusses the impact of additional binaries on release management and deployment w.r.t. OData WebApi.
Maybe I'm not fully understanding your example. If not, could you help me better understand?
When can we expect a first version of OData on ASP.NET Core? Is it the feature/netcore branch?
@robward-ms I've read your comment and I'm satisfied with that. Let's start a journey!
@rendmath - From my earlier comment, We hope to have an alpha on NuGet in the next several weeks. Yes, it is accumulating in the feature/netcore branch which got it's first commit yesterday. There are a total of 9 steps/PRs to get current project refactored for the AspNetCore component, I have step 2 in PR now.
We are super excited for this..! Will this release support EF v6 & EF Core? @TonySneed
@lelong37 - For EF Core support, #669. This item only tracks ASP.Net Core support.
@robward-ms ASP.NET Core can target either .NET Core (EF Core) or the full .NET Framework (EF 6). (See my demo: https://github.com/tonysneed/Demo.AspNetCore2.EF6.) So you're saying that OData Core will only support .NET Core (EF Core) and not full .NET Framework (EF 6)? /cc @lelong37
@tonysneed - I'm trying to say this GitHub issue tracks the ASP.Net core work only. We should track EF in separate issues and #669 is one of those.
@robward-ms Got it -- I'll check over there. Thanks!
mh, what about this maintenance-aspnetcore branch? It targets .NetStandard 2.0 and there is a sample project that targets netcoreapp1.0
maintenance-aspnetcore is a branch originally forked from the 5.7.0 version of OData WebApi. It has gone through a few changes and the samples may not match the product at this point. The feature/netcore branch will borrow code form there but not necessarily ship in the same form.
Our plan for the feature/netcore branch is to target both AspNetCore 1.x and 2.x as well as AspNet 5.x. To do this, we'd compile OData WebApi as a NetStandard 2.0 dll, a NetStandard 1.3 dll and a net45 dll similar to what's in the existing OData WebApi package.
We'd love some feedback on this plan. Honestly, AspNetCore 1.x is a harder target to hit due to changes in the reflection namespace in NetStandard 1.x but we're trying to be as flexible as possible on our side and accommodate those who want to run on any of these platforms.
Thoughts?
Personally I wouldn't bother with AspNetCore 1.x, as there was no official .NET Core release most will migrate from .NET 4.x to AspNetCore 2.
I was going to create a new AspNetCore 2.0 project with OData, but it's not available. I will be skipping AspNetCore 1.x for any projects. I feel that AspNetCore 2.0 is more mature. With OData not being ready, I am disappointed and must go back to creating net45+ projects with OData instead.
I wonât be using AspNetCore 1.x either, but Iâm very excited about OData on 2.x !
I also would love to see odata on asp net core 2 without wasting time on asp net core 1.x.
I also cannot imagine that there will be many projects that settle on asp net core 1.x with a need for odata.
@jannikb-sim I would suggest that more information would be needed to make that assumption, I personally while using aspnet core 2.0 for web development use .net standard 1.3 & 1.6 for libraries so lesser versions can use them. So in short it the standard that should targeted and if the apis in the standard are available to make it work use the minimum
true, its just an assumption
Agreed, OData for ASPNetCore v2 should be the focus, would go as far as OData for ASPNetCore v1 not even needed. The reality in the enterprise was really to wait for ASPNetCore v2, being that there was quite the anxiety with the frequency of (breaking) changes for both NetCore, ASPNetCore, EFCore to a arrive @ v1 as well as parallel efforts on .NET Standard API Spec. Now with all things Core v2 release behind us, as well as .NET API v2.0 Specification, think there is a very positive outlook on stability, reliability and the .NET community starting to truly understand the whole .NET Standard API Spec. Last but not least, with many enterprise teams/projects also not making the leap to ASPNetCore v1 due to their dependency on OData being deeply embedded in our architectures as well as being the defacto REST strategy for many of us (kudos to the team, OData is simply awesome and arguably the best way to implement REST architecture, from a REST resource querying perspective with the best implementation of fine granular control of object graph payloads coming across the wire). In short, most teams that are running ASPNetCore v1 obviously aren't using OData anyway. However all teams that have a dependency and are waiting OData before crossing over to ASPNetCore can just make the leap directly to ASPNetCore v2, and why wouldn't they? If your going to cross over, make so the most sense to directly go to v2. @robward-ms @yesman85 @BruceHunter @toxik @jannikb-sim @tonysneed
Agreed, we also plan to skip on ASPNetCore 1 and go straight to ASPNetCore 2
On Thu, Sep 28, 2017 at 10:46 AM Long Le notifications@github.com wrote:
Agreed, would really just focus on ASPNetCore v2+, the reality in the
enterprise was really to wait for ASPNetCore v2, being that there was quite
the anxiety with ASPNetCore alpha making to to official v1 as well as the
frequency of (breaking) changes for both NetCore & ASPNetCore to a arrive @
v1. With Core v2 behind us, think there is a very positive outlook on
stability and reliability. Last but no least, with many enterprise
teams/projects also not making the leap to ASPNetCore due to dependency on
OData being deeply embedded in our architectures as well as OData being the
defacto REST strategy for many of us. Again, OData for ASPNetCore v2 should
realy be the focus that makes the most sense both from timing perspective,
community confidence in terms of NETCore, ASPNetCore, EntityFramework Core
v2 API and overall stability.â
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/OData/WebApi/issues/939#issuecomment-332756006, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABo2WSZIa5RaH-OTuaY8GpocYzZtMoijks5sm07AgaJpZM4MaldT
.
Any updates on when the alpha will be ready?
+1
On Mon, Oct 2, 2017 at 4:02 AM gordon-matt notifications@github.com wrote:
Any updates on when the alpha will be ready?
â
You are receiving this because you commented.Reply to this email directly, view it on GitHub
https://github.com/OData/WebApi/issues/939#issuecomment-333419812, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABo2Wc2SX5khjzU3wURuNXUDAXbQpubPks5soDYXgaJpZM4MaldT
.
+1
Any ETA on even an alpha version? We're using OData extensively and are looking to move a large app of ours to DotNet Core v2 but we're holding off until there's OData support available.
FWIW we're not interested in DotNet Core v1 support either.
Thanks for the feedback on AspNetCore v1 vs v2.
Yes, I was a bit vague at the end of August with "We hope to have an alpha on NuGet in the next several weeks". I'm still a few weeks away from having something to test. I think coding-wise I'm 1-2 weeks away from that but I suspect code review will add another week.
The feature/netcore branch now has a compliable AspNet (not core) product dll without tests. Steps 5-8 will add the unit and E2E tests; this work is done and waiting on PRs to complete. 'd like to have this all reviewed and committed by the end of next week.
What's on my dev box is the AspNetCore-specific components for a basic service, which includes model building, routing & formatting. I'm not sure exactly the best way to get these changes through the PR process but I suspect you'll start to see PRs rolling out the week after next (week of Oct 16th). The early stages of those PRs probably won't be functional, I think it might take another week (week of Oct 23rd) to get a functional AspNetCore product in features/netcore.
It will likely be end of Oct/early November before tests and docs for AspNetCore start showing up in PRs.
@robward-ms kudos on the transparency! That's exactly the kind of response I like to hear.
@robward-ms sounds aweseome! Thanks for the insights
@robward-ms Thanks for the update - and thanks for all your work. It'll be great to get going with it.
+1 on the OData support. I already have a project in mind. How can I help or at least keep myself up to date? I'm already a MSFT Github user so I have passed the onboarding process.
@robward-ms - Thank you for the transparency. We can plan accordingly on our road map for changes we need to make use .net standard 2.0
@robward-ms - Could you please let us know the tentative date by when we can expect ALPHA version? Thank you.
I'm currently running about 2 weeks behind where I wanted to be. I had planned to start rolling out AspNetCore PRs the week of Oct 16th but they are starting this week instead. 2 PRs to come before AspNetCore code, then it will be in a couple of PRs.
Similar to my comment before, the early stages of those PRs probably won't be functional, I think it might take another week (now week of Nov 6th) to get a functional AspNetCore product in features/netcore. I'm hoping to have an Alpha around the 13th but I may again be too optimistic in getting this code through review and committed.
As of now, the AspNet product is again functional in feature/netcore. We have a build setup and producing nightly packages, you will find the nightly for the AspNet version (NOT AspNetCore) there now: https://www.myget.org/feed/Packages/webapinetcore. When the AspNetCore alpha is ready, it will start showing up here as well.
Sorry for asking, I currently am in the process of learning the ASP.NET Core stack and still need to wrap my head around a lot of the new things.
I have next to no experience with the old ASP.NET framework, regardless I wanted to get started with OData in ASP.NET Core.
Can I for the time being use the Microsoft.AspNetCore.OData v1.1.0-alpha1 version from NuGet to experiment and learn OData? Is this the version associated with the maintenance-aspnetcore
branch of this repo?
I suppose I'd need to do some migration work as soon as you publish an Alpha package of the feature/netcore branch which wouldn't concern me much since I just use it to learn OData right now.
@ebeeb I would be cautious about that NuGet package. It does not appear to be Microsoft sanctioned as far as I know.
@robward-ms Keep up the good work and thank you for the updates!
@ebeeb , @robertmclaws is right. While the package is named "Microsoft.AspNetCore.OData", it not actually a Microsoft published package. I believe the code used to build it is a fork from this repo, and it kinda looks like maintenance-aspnetcore, but I can't say for certain if it will help you in this case.
I can say that there is a fair bit of code going into features/netcore that comes from maintenance-aspnetcore but it will not be backwards compatible. I've tried pretty hard to keep the existing API signatures for AspNet in the AspNetCore version but a few things have changes due to API differences between AspNet in the AspNetCore.
I hvae read the whole thread, but still needs a clarification.
When Odata for ASP.NET Core is published, it will work on .Net full framework only or it could also be run based on .Net Core too? I am going to use OData on a Linux machine that only has .Net Core not .Net full framework.
@afsharm Odata for ASP.NET Core work on netstadard
Thank you @genusP for your reply. From net-standard guide, I know that both .Net Core 2.0 and .Net Full Framework 4.6.1 implement .Net Standard 2.0. Which version of net-standard do you mean?
For ASP.NET Core 1.x netstandard1.6 and netstandard2.0 for ASP.NET Core 2.x
@robward-ms Thanks for the clarification. Regardless, I'm going to use the Microsoft.AspNetCore.OData package then or try to compile the maintenance branch myself. Backwards compatibility is not really an issue for me and for experimenting only. "Migrating" the demo code will just be a learning experience for me :) Like migrating my Demos from AspNetCore 1.1 to 2.0 was.
Keep up the good work đ
what I really don't get is why that strict focus to EF? OData is a protocol, it can do a lot, but basically having it for just querying would be fantastic - and having the possibility to query any IQueryable
now this was possible via MVC5 API: with a small "fix" just using the EnableQuery attribute we could have OData queries and odata-like output: https://gist.github.com/hidegh/565522d6fab71f2042fc0e145d4ddb8e also case-insensitive mode was possible, althoug for just camleCase a but more code was necessary: https://gist.github.com/hidegh/6f94a671c9a9df05aa02b7baedab051a - still any of the above code was not using EF.
now for MVC6 (full DNX support via 1.0.0-rtm-00015 and now core2.0 suport for 1.0.0-alpha1) the https://www.nuget.org/packages/Microsoft.AspNetCore.OData/ was a nice shot. I was trying to get it work by the simple way, without luck. So only the more complex solution was working for me (full dnx 4.6.*) https://gist.github.com/hidegh/5268a456a170d99e4be6cd0b4692d3c1
so what I do see: we got a nice standard here, but there's no lightweight implementation for it (not to mention missing config if we don't want to have ODataController in MVC5) and so we can't use it for the most basic situations (query) [especially not in MVC6]...
[I still do remember those custom filter I have created with generic type and queryable extensions...]
@genusP , @afsharm - From today's commit, you can see I'll be targeting AspNetCore 2.x using NetStandard 2.0.
@hidegh - I'm a bit confused by your comment, WebApi does work with IQueryable and is not solely focused on EF.
It looks like from your gist's that you are looking for an OData implementation using just an ActionFilter?
@hidegh If you need (like me) to use the OData syntax outside the context of a web app, you may want to look at my request: https://github.com/OData/WebApi/issues/1054
@robward-ms Hi, Rob. Yes. Exactly. I do wanna use OData without "extra" configuration (separate odata controller/route). I know OData is capable of much more, but let's admit, basic CRUD operations can be made without OData on a WebAPI. The querying (tables) is the major repetitive work on every project and here is where OData can really shine.
Also what I miss is the way to configure ConventionalModelBuilder (to use camel case) when you just have something like this:

With just such a config:

@raffaeler Actually we do solve both similar issues (even if I do have a focus on WebAPI). Since what odata querying is about is: parsing, applying the parsed values to an IQueryable and returning the result (with count) in an OData like structure (this should be a separate attribute in WebAPI and a separate aspect ~ AOP ~ to run in other kind of solutions).
[final thoughts: it's really a fine community, after contributing with some notes on the EF core, I'm happy to see that this "forum" and people here are so constructive!]
Aren't most of these issues related to RESTier, rather than to OData/WebAPI, strictly speaking?
As far as we are concerned, a port of RESTier to .NET Core is the one and only reason we're following the migration of this library with so much enthusiasm.
@rendmath No, RESTier is an another layer above OData, where based on some URL conventions you get a full CRUD model (simplicistic view). So for RESTier the EF-layer (a way to do writes) is a must.
My proposal is only about querying (reading), with no write operation. As I said it's just parsing the query and applying those values to an IQueryable :D
Frankly, I don't understand why getting Restier on NetCore is such a big deal. You should NOT be building your web APIs into your web apps, you should keep them separate for scalability. I have 9 Restier services in production right now on .NET 4.6.2, being used by .NET Core apps. Separation of concerns, people!
The ONLY benefit you'll get on .NET Core is throughput, or Linux hosting. But Restier still has way too many bugs to worry about cross-platform at the moment.
I just want a shipping version of Restier that is complete, well documented in readable English, doesn't break on $count, and doesn't rely on unit tests to be developer samples.
@robertmclaws I don't know anything about Restier, but I _can_ tell you that having separate apps is not always an option. It's rarely even a necessity, as most apps don't need to scale.
@robertmclaws actually the issue is not Core or Full .NET framework with .NET Standard 2 you should be able to be compatible with both. Currently the issues are MVC5 (MVC and WebAPI) layer vs. MVC6 layer (architecture, topology). Both API and RESTier is dependent on the MVC version.
I do share your opinion on scaling, this is why:
@alexdresko I haven't used RESTier, but try to look at it as an extension/layer over OData, which simply enables you to do CRUD operations, with some standardized URLs (by conventions) without extra code. I do really prefer querying and custom create/update/delete ... but must admit, RESTier and it's URL conventions should be used in any API Routes (some people are really bad at creating meaningful URL names :D)
@hidegh I understand what the current issues are. As I mentioned, I have 9 Restier apps in production.
Microsoft is already working on a version that works on ASP.NET 4 and ASP.NET Core 2. So I'm not sure why everyone here is arguing the benefits for it when it is already happening. Just have some patience.
Regarding your issue with boilerplate code, that's what Restier is for. Restier = WCF Data Services ++. If you don't like the way they do it, you should build your own framework. But honestly, the URL and query structure are already part of an open standard, so good luck getting people to use something else.
Straight up, just being honest, it sounds like you need to read the spec and understand the tooling a bit better, because the way you phrased your post on the "strict focus on EF" shows that you don't really understand how WebAPI+OData works... yet you're trying to explain it incorrectly to everyone else.
@robertmclaws OData is .NET standard, right, know it - and OData itself is OK. Do you have any direct/live links on the OData MVC6 integration from Microsoft?
Here we are in the OData/WebAPI forum. And while we got a Microsoft.AspNet.OData for MVC5 WebAPI we still not have other than a Microsoft.AspnetCore.OData for MVC6 with a single contributor (reason people are asking MVC6 support here are related to MVC integration, not directly with the OData lib). BTW: right for this kinda of integration have I suggested the split between core with query and write operations on the solution over that MVC layer (what most coders would use from OData is querying first - to remove any repetitive or custom code just to have filterable tables) - just to have something at hand sooner - and IMO querying over an IQueryable<> (since I did in the past custom code for it) is much more simpler than the rest...
@hidegh yes, I am also already using oData out of context, but currently you still have unwanted dependencies and the code must "simulate" a web call to make the transformation from string to expression happnen ... too bad.
But I really hope the team is working in the direction to totally decouple these pieces and allowing to use the various oData pieces indpendently from asp.net(traditional or core). This is why I opened that issue (and another one to make expression trees better looking and with no use of private types).
Good luck ;)
@robertmclaws I agree with you that getting RESTier on .NET Core is not, by itself, such an important goal. Our actual hope is that, once OData is moved to .NET Core, Microsoft will dedicate more resources to RESTier, and finally get us to a stable and well-documented v1.0.
@robertmclaws i've had a private conversation, and must admit, @raffaeler is right, basic OData lib is not able to "extract expressions from an odata string. It is not even enough to easily create a model with the ConventionalModelBuilder. Once you add the reference to the Microsoft.Aspnet.OData, you get a lot of unwanted dependencies (and lose the opportunity to run on netcore).".
@rendmath I believe that is the plan. They're moving up the stack: revising, refactoring, and prepping for .NET Core support. Once that is in place, a shipping Restier should be able to run on either platform.
It may take a little extra engineering work to get there, though. And a LOT of extra documentation work.

@xiaoxin1983 there is no mvc6?
@xiaoxin1983 This is an interesting conceptual design, but there are a lot of mistakes. MVC6 is not a thing it should be MVC5, WCF is not supported anymore, neither are XML payloads. Restier should be right next to MVC5, and cover both MVC 5 And MVC Core.
Instead of "others" you might consider replacing that with "POCOs", as really you can query over any object, doesn't matter how that object is materialized.
HTH!
MVC6 has been renamed to just MVC for AspNetCore and so far has aligned with the versions for AspNetCore. My understanding is that the version has reset as it's a different (core) product. In Nuget it's referred as Microsoft.AspNetCore.Mvc.Core 2.0.0.
Guys, all these conceptual things are very nice and important. But. Here we are, simple programmers, who still can not use ASP.NET Core because OData support is not here yet. I'm now starting 3rd project in a row and I have to select the old ASP.NET just because of lack of OData support. Is not this shame?
Why not you release something working for us, simple people. Something ugly in design, but working. Then you can spend all time you need polishing designs.
I know all I'm saying here is not very polite. But. Situations like this one are what may result in CORE endeavor failing. It is really-really strange that MS does not understand this simple fact.
@dmytro-gokun First, I think you mean WebApi support for OData as OData does work with dotnet core. The main problem is that MVC and WebApi merged into one product for ASP.Net Core. WebApi for OData relied heavily on an architecture that no longer exists in the core products and has to be redesigned. It would be very costly to have designed this earlier when the product was changing, and I'm sure they didn't want to delay the shipping of dotnet core to align these products. I know I didn't.
I personally looked at the early ports of OData WebApi to ASP.NET core and made it work for my own project but it was very buggy and a mess IMO. You could have done that yourself if you wanted to. There was even unofficial Nuget packages out there that took snapshots of their progress if you were brave. So yes, you can do that but I wouldn't recommend it.
Hi , yes i make a mistake , i was thinking mvc5, but typed mvc6 .
i think odata lib or odata webapi can be a framework ,then it can connect many data provider like ef, and connect many http request provider like aspnetcore. it just provide exchange power:
and then odata provide some default ImplementsïŒaspnetcore ,efcoreïŒ
FYI
Alright guys, I'm sorry to have to do this, but I'm locking this conversation for now, as it is distracting from the work that is being done. Unlocking the thread but changed the title of the issue. I would close this bug, but the work is not actually done yet.
For like the 5000th time, OData for .NET Core is _in progress right now_, and ALMOST FINISHED.
Imagine the engineering that is going on right now, building a system that is compatible with two disparate frameworks. Microsoft isn't updating ANYTHING ELSE in ASP.NET 5.2.3, _except for this_.
So instead of whining that you've had to use the "old" ASP.NET for OData stuff (when in a cloud-based world, you should be splitting your APIs from your UI code ANYWAYS) try spending a few minutes cheering on the team getting the work done.
Because Microsoft could have very easily killed this project and left us all high and dry.
@robertmclaws you make a good point with regards UI & API separation; but I would be very surprised if Microsoft killed the project given the number of there products using OData both internally/externally and in azure ;)
I believe we all know that the Microsoft Teams are working hard to achieve this, I'm wondering if all the development will be open source ? if so would it be of benefit to allow the community to help with development/testing/documentation etc.
@grahamehorner You shouldn't be surprised. It almost happened. And the work _already is_ open source, it's happening on other branches in this repository.
Just wanted to drop a shoutout to @robertmclaws @robward-ms and all the other folks working to make this possible. I've been in the saddle so many times before, being part of a group that was reassembling a 747 mid-flight. You gals and guys working on this are fantastic. Keep it up!!!
Hello there,
just a little tactical whine to make sure if it's almost finished like for the past half-year.
Cheers.
odata .net core will drop on Christmas Monday, December 25.. Microsoft loves to do stuff like that..
Hi Guys,
It would be great if we know the approximate time for the beta version. Thanks for your hard work!
@AlexanderBatista, it is reliable information or your assumption?
@djuuuuus It's definitely not reliable information, and if @AlexanderBatista made an assumption, it's a poor one. I've been in this business 20 years, and AFAIK Microsoft has never dropped bits on the holidays; they are always OOF for the last two weeks of the year. There may be occasional exceptions for Windows Insider builds, but not usually. Some teams save up their vacation time and take the whole month of December off.
If it's not out by December 15th, it won't be out until January 15th, at the earliest. That's pretty standard for Microsoft stuff.
@KrzysztofPajak As for timelines, you should set your expectations that it will be out in mid-January. If they get to it sooner, great. But the next 4 days are a holiday, then you have 15 working days until Christmas. Watching the work that is being done, I just don't think it will be ready by then.
Trust me, you want them to be as thorough about this as possible. And we need a robust enough Beta to be able to track down and fix bugs.
Once again, this is not official communication, just my educated observations from getting every single GitHub e-mail about this project, HTH!
Just wanted to say I am eagerly awaiting Odata for .net core.
Do I have to compile this or is there a build I can Nuget?
On Thu, Nov 30, 2017 at 6:38 AM Yan notifications@github.com wrote:
Beta odata net core https://github.com/OData/WebApi/tree/feature/netcore
â
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/OData/WebApi/issues/939#issuecomment-348176654, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AM-qVq_qN26yLjx8dy0gdECOuv6AhQumks5s7qHLgaJpZM4MaldT
.>
Tony Valenti
@djuuuuus Doesn't know what he's talking about. There is no beta, yet.
@alexdresko @djuuuuus has dashed my hopes :'( not nice when everyone is working flat out to have someone post an untruth about a work-in-progress getting release in any form; especially during a period when a lot of the team is having a holiday period
You guys are taking the obvious sarcasm way too seriously.
Kudos to the team working on this, its a complex project. There is a little bit of over promise and under deliver regarding ETA here, but the team is trying to leave you a little hope, due to being just as eager to get it out the door. Its a shame they get bit by trying to be more transparent.
If we want something to really complain at Microsoft about for dropping the ball, it would be a Xaml designer for Xamarin Forms and SkiaSharp. I don't see anywhere near that level of negligence with odata.
@djuuuuus - https://github.com/OData/WebApi/tree/feature/netcore is a bit less than Alpha at this point, the current PR (#1138) helps that quite a bit though.
@TonyValenti - for https://github.com/OData/WebApi/tree/feature/netcore, you have to compile it yourself at this point. However, without the current PR (#1138), it's not terrible functional.
@dapug - Thanks for the support.
@robertmclaws is spot-on w.r.t. to scheduling. We don't plan to release over Christmas.
Sorry I've been silent for a while, The current PR, #1138, will bring OData for AspNetCore to an Alpha state. I've got more than 60% of the UTs running but not passing all tests (as of right now, 183 failed & 5146 pass). My plan is to commit #1138 tomorrow morning, then put another PR with some cleanup (FxCop + doc comments) and Nuget packaging. I plan to commit that tomorrow (maybe the weekend) as well and start publishing the Alpha on myget: https://www.myget.org/feed/Packages/webapinetcore
My current plan is to release an Alpha on MyGet by Monday Dec 4th and a Beta version of AspNetCore on Nuget on Dec 15th.
@robward-ms I canât say it enough, you and everyone involved in this effort rock. Cannot thank you enough. As a show of support, when the beta drops Iâm going to give up my Saturday to try and build something functioning to help certify it.
@wmccullough @robward-ms Iâll be doing something also as a learning/testing excersie when the beta drops đ€ đ as Iâve got a few odata client components that have integration tests with classic asp.net odata which Iâll be updating and will feedback
@robward-ms Thank you very much for your great work and also for the information you provided regarding the timeline. Knowing these dates, we can move forward and plan our projects more accurately. I really appreciate it.
The AspNetCore alpha package is available here: https://www.myget.org/F/webapinetcore/
Feel free to file issues but please mark them as AspNetCore, either with [feature//netcore] in the title (like #1134) or by applying the feature/netcore label.
There is no docs or samples yet, here is an example Startup class:
public class Startup
{
public Startup() {}
public void ConfigureServices(IServiceCollection services)
{
services.AddOData();
services.AddSingleton<SampleContext>();
}
public void Configure(IApplicationBuilder app)
{
IEdmModel model = GetEdmModel(app.ApplicationServices);
app.UseMvc(routeBuilder => routeBuilder.MapODataServiceRoute("name", "prefix", model));
}
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
...
return builder.GetEdmModel();
}
For anyone having problems with the myget URL mentioned above... Here you go: https://www.myget.org/F/webapinetcore/
I created a new project to try this out and only 1 ODataController. However, I keep getting a NotImplementedException on startup. The stack trace is as follows:
Microsoft.AspNet.OData.FromODataUriAttribute.get_BindingSource()
Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo.GetBindingInfo(IEnumerable<object> attributes)
Microsoft.AspNetCore.Mvc.Internal.DefaultApplicationModelProvider.CreateParameterModel(ParameterInfo parameterInfo)
Microsoft.AspNetCore.Mvc.Internal.DefaultApplicationModelProvider.OnProvidersExecuting(ApplicationModelProviderContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionDescriptorProvider.BuildModel()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionDescriptorProvider.GetDescriptors()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionDescriptorProvider.OnProvidersExecuting(ActionDescriptorProviderContext context)
Microsoft.AspNetCore.Mvc.Internal.ActionDescriptorCollectionProvider.UpdateCollection()
Microsoft.AspNetCore.Mvc.Internal.ActionDescriptorCollectionProvider.get_ActionDescriptors()
Microsoft.AspNetCore.Mvc.Internal.AttributeRoute.GetTreeRouter()
Microsoft.AspNetCore.Mvc.Internal.AttributeRoute.RouteAsync(RouteContext context)
Microsoft.AspNetCore.Routing.RouteCollection+<RouteAsync>d__9.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
Even if I remove the new code in the Startup class, the error continues.
If you need further details, here you go:
My ODataController:
public class PublicUserApiController : ODataController
{
private readonly ApplicationDbContext context;
public PublicUserApiController(ApplicationDbContext context)
{
this.context = context;
}
public virtual IEnumerable<PublicUserInfo> Get(ODataQueryOptions<PublicUserInfo> options)
{
var settings = new ODataValidationSettings()
{
AllowedQueryOptions = AllowedQueryOptions.All
};
options.Validate(settings);
var query = context.Users
.Select(x => new PublicUserInfo
{
Id = x.Id,
UserName = x.UserName
});
var results = options.ApplyTo(query);
return (results as IQueryable<PublicUserInfo>).ToHashSet();
}
public virtual async Task<PublicUserInfo> Get([FromODataUri] string key)
{
var entity = await context.Users.FindAsync(key);
return new PublicUserInfo
{
Id = entity.Id,
UserName = entity.UserName
};
}
}
public class PublicUserInfo
{
public string Id { get; set; }
public string UserName { get; set; }
}
And the Startup class:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddOData();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
var edmModel = GetEdmModel(app.ApplicationServices);
app.UseMvc(routes =>
{
routes.MapODataServiceRoute("OData_Kore_Web", "odata/kore/web", edmModel);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
builder.EntitySet<PublicUserInfo>("PublicUserApi");
return builder.GetEdmModel();
}
}
All I did was create a new ASP.NET Core app with the "Individual User Accounts" option for authentication and then added the ODataController and made the few changes in the Startup class as above. Oh, and I also updated all nuget packages to the latest if that makes any difference. That should be about it really. Nothing weird.
@gordon-matt - the FromODataUriAttribute is on the TODO list, it's not implemented yet: https://github.com/OData/WebApi/blob/feature/netcore/src/Microsoft.AspNetCore.OData/FromODataUriAttribute.cs
I filed this issue: #1142
Also, thanks for the correct link for subscribers, the link I used is for owners. I update my original message with your link.
hi there, im glad there is finally an pre alpha to to try +1.
i have one issue:
using swagger fails InvalidOperationException: No media types found in Microsoft.AspNet.OData.Formatter.ODataInputFormatter.SupportedMediaTypes
Edit:
this is solved:
EnableQueryAttribute throws while triing to get IEdmModel from DI
returning ok() with IQueryable throws while triing to get ODataSerializerProvider
i had to remove this from my controller:
[Route("odata/Companies")]
after removing the attribute swagger has more problems:
Multiple actions matched. The following actions matched route data and had all constraints satisfied:
Playground.core.Controllers.CompaniesController.GetSingleCompany (Playground.core)
Playground.core.Controllers.SitesController.GetSingleSite (Playground.core)
and finally:
should the namespace really be Microsoft.Aspnet.Odata id expected Microsoft.AspnetCore.Odata
If you need repro here is my code: https://github.com/JanEggers/Playground/tree/odata
anyway really good work keep PR comming!
@JanEggers - I looked at your repo, I wanted to clarify: commit 5b50b08aaa7c819af5473e3571b73ebcf04fe0b8 fully fixes the issues you were seeing?
For the namespace, yep we're planning on a single namespace for both products and landed on Microsoft.Aspnet.Odata for back-compat reasons: back-compat is increased if shared and AspNet use a single namespace, making a 6->7 upgrade a NS change only and partial classes need to also use the shared NS so I went with Microsoft.Aspnet.Odata wholesale.
We have considered dual namespaces but that would require that the common code has #if for using's & namespaces and increases the likelihood that making a change in shared core REQUIRES editing both AspNet and AspNet core projects; it's possible to make a shared code change in only one project now and use the command-line build to verify the other change without opening both projects. In short, dual namespaces will increase code maintenance cost.
I'd love to get some feedback on the NS issue.
fully fixes the issues you were seeing?
nope. using /swagger still produces InvalidOperationException: No media types found in Microsoft.AspNet.OData.Formatter.ODataInputFormatter.SupportedMediaTypes
im currently looking at https://github.com/rbeauchamp/Swashbuckle.OData maybe i can provide a pullrequest there to support AspnetCore.Odata
@JanEggers - Ah, I do have a bit more work in Formatting. including refactoring and media type mappings. You may be seeing a limitation of the Alpha. I filed #1144
thx again for your efforts
@JanEggers I have been looking at your OData branch of your playground application and was wondering if you have come across any errors/issues around using "$select", "$count" and "$top".
Here are some example URL's and errors I am getting:
http://localhost:63980/odata/TestResult?$count=true
{
"@odata.context": "http://localhost:63980/odata/$metadata#Edm.String",
"value": "The query specified in the URI is not valid. Unable to resolve service for type 'Microsoft.AspNet.OData.Query.DefaultQuerySettings' while attempting to activate 'Microsoft.AspNet.OData.Query.Validators.CountQueryValidator'."
}
http://localhost:63980/odata/TestResult?$top=1
{
"@odata.context": "http://localhost:63980/odata/$metadata#Edm.String",
"value": "The query specified in the URI is not valid. No service for type 'Microsoft.AspNet.OData.Query.DefaultQuerySettings' has been registered."
}
http://localhost:63980/odata/TestResult?$select=Id
I get a stack trace
System.ArgumentException: The type 'Edm.String' is not an entity type. Only entity types support $select and $expand.
Parameter name: context
When hitting the following URLs It works as expected e.g.
http://localhost:63980/odata/TestResult
{
"@odata.context": "http://localhost:63980/odata/$metadata#TestResult",
"value": [
{
"TestId": 0,
"ParticipantId": 8,
"StartedAt": "2017-12-04T13:16:24Z",
"EndedAt": "2017-12-04T13:16:30Z",
"Id": 0,
"DeletedOn": null
},
{
"TestId": 0,
"ParticipantId": 9,
"StartedAt": "2017-12-04T13:16:24Z",
"EndedAt": "2017-12-04T13:16:30Z",
"Id": 1,
"DeletedOn": null
}
]
}
After some googling I added the following to the StartUp file
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
var es = builder.EntitySet<TestResult>(nameof(FDbContext.TestResult));
builder.EntityType<TestResult>()
.Count().Filter().OrderBy().Expand().Select(); //This line is aaded for $select, $count,$filter, $top and $select
return builder.GetEdmModel();
}
I then added
[Count]
[Select]
[Filter]
To the TestResult class.
I am using the following setup
I have had a look at the following links and tried them and still no difference.
http://odata.github.io/WebApi/#13-01-modelbound-attribute
Has anyone else seen issues like this?
@robward-ms Thank you so much for all the hard work this holiday season. great work and thanks regarding the timeline. I think everyone here really appreciates the work being done
@lemex92 i just verified your findings and jup all queries are not working because DefaultQuerySettings are not registered.
it will take some time to get all the goodness back to working state
Awesome, For now, I think we are just going to use the .NET Framework for our OData API and use .NET Core for the rest of our application.
Once .NET Core has the full OData functionality we will switch back. Do you have any recommendations/resources on sharing our data/model project between .net core and standard .net?
Am I screwing up my config somehow? I keep getting an error related to ODataQueryOptions binding.
'''
InvalidOperationException: Could not create an instance of type 'Microsoft.AspNet.OData.Query.ODataQueryOptions`1[[Proj.Data.Entities.Resource, Proj.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor.
'''
Nope, it's not you, it's me. I'll have a PR & build for it in a bit.
Thanks, glad to see this making headway. I appreciate you an your work here. :)
@kyse - Thanks for testing and your patience. I had to lines of code in ODataRouteBuilderExtensions.cs that I thought were not needed but when missing caused about 1300 test failures. I don't have tests in feature/netcore yet so I'm trying to keep feature/netcore and my dev branch (where I have about 70% of the UTs passing) synced manually. #1148 converges them and resolves this issue with a temporary fix. I'll have a new package on MyGet later today.
@kyse - This fix is in Nightly201712042322 on MyGet.
I think what I'm seeing is more related to ODataQueryOptions constructor not ODataOptions, doesn't appear your changes helped me. I didn't see anything related to model binding in your example above, I've got to be missing something obvious.
@kyse - Do you have a larger call stack or sample?
System.InvalidOperationException: Could not create an instance of type 'Microsoft.AspNet.OData.Query.ODataQueryOptions`1[[Proj.Data.Entities.Resourcec, Proj.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor.
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.<BindModelCoreAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.<BindModelAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
Is
@kyse - Can you share your controller code?
using System.Collections.Generic;
using System.Linq;
using Proj.Data;
using Proj.Data.Entities;
using Microsoft.AspNet.OData;
using Microsoft.AspNet.OData.Query;
namespace Proj.Server.Controllers.odata
{
public class ResourceController : ODataController
{
private readonly ApplicationDbContext _context;
public ResourceController(ApplicationDbContext context)
{
_context = context;
}
public virtual IEnumerable<Resource> Get(ODataQueryOptions<Resource> options)
{
var settings = new ODataValidationSettings()
{
AllowedQueryOptions = AllowedQueryOptions.All
};
options.Validate(settings);
var query = _context.Resources;
var results = options.ApplyTo(query);
return (results as IQueryable<Resource>).ToHashSet();
}
// Pending FromODataUri implementation - https://github.com/OData/WebApi/issues/1142
//public virtual async Task<ApplicationUser> Get([FromODataUri] string key)
//{
// var entity = await _context.Users.FindAsync(key);
// return new ApplicationUser
// {
// Id = entity.Id,
// UserName = entity.UserName
// };
//}
}
}
@kyse - Thanks. It caused by ODataQueryParameterBindingAttribute not being implemented, I filed #1149.
ODataQueryOptions is marked with that attribute to get it from dynamically from the request. Since it's not yet implemented, AspNetCore looks for it in the dependency injection container, hence the failure.
Thanks for all the work you're doing. I'm having issues trying to get anything at all to work though. Using my example in a comment above, I kept getting a 404. I updated to the latest fix that you deployed and now it's an HTTP 500 error instead. This is the message:
InvalidOperationException: Could not create an instance of type 'Microsoft.AspNet.OData.Query.ODataQueryOptions1[[OData_Test.Controllers.OData.PublicUserInfo, OData_Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor.`
That class is not abstract and I don't see a problem with the constructor, since I haven't specified any and it would thus use a default constructor:
public class PublicUserInfo
{
public string Id { get; set; }
public string UserName { get; set; }
}
EDIT: Sorry for duplicate error... I just noticed @kyse has the exact same error
Hi All,
I have a desktop app (not a web app) that is using EF Core and is exposing lots if its data through an HTTPListener. How would I expose an OData endpoint using an HTTPListener?
Hi,
I can't use specific form attribute "FromBody" in ODataController. After sent request my parameter always has null.
Class track changes "Delta" doesn't work in ODataController.
@KrzysztofPajak -
The "FormBody" issue is fixed in the latest PR but it's not checked in yet: #1157
For Delta, could you file an issue?
Just got the latest version. I no longer have the InvalidOperationException regarding the parameterless constructor, but now there is a new exception instead, as follows:
SocketException: The attempted operation is not supported for the type of object referenced
System.Net.IPAddress.get_Address()
Stack Trace:
System.Net.IPAddress.get_Address()
Microsoft.Extensions.Internal.PropertyHelper.CallNullSafePropertyGetter<TDeclaringType, TValue>(Func<TDeclaringType, TValue> getter, object target)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry.get_Model()
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, string key, object model)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, string key, object model)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, string key, object model)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, string key, object model)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, string key, object model)
Microsoft.AspNetCore.Mvc.Internal.DefaultObjectValidator.Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model)
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder+<BindModelAsync>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider+<>c__DisplayClass0_0+<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeInnerFilterAsync>d__14.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
@gordon-matt - Could you open a new issue and possible supply a link to a repo project?
@robward-ms Thanks for the response. If you look at my post from 12 days ago you will find all you need right there (very basic usage). Let me know if you still prefer a separate issue to be opened and I'll be happy to do so.
EDIT: I just uploaded the test project. Here's the link: OData_Test
To see the problem, just run it and browse to: /odata/PublicUserApi
@gordon-matt - I did look back and scanned the code again and did not see anything that looks out of place. Yes, please file an issue so we can track it's status somewhere other than here, since this issue will likely get closed once the Nuget package is available. From then on, issues will be the best place to track things.
@robward-ms Done as requested. See Issue #1165
Time for a status update. 15 days ago I said:
My current plan is to release ⊠a Beta version of AspNetCore on Nuget on Dec 15th.
Well, itâs the 15th but sadly I donât think the code is ready for Beta. Iâm done with all the code that I know needs to be written except for Batching (itâs in progress). However, I donât have good validation yet. Iâm close enough to getting E2E test running that I think Iâll be done next week.
A few folks have picked up the Alpha and reported back, mostly with issues. Some of those have been fixed but not all. There has not been a lot of feedback saying âIt works great!â so some other form of validation is needed for Beta.
I do have unit tests running, about 90% with ~ 2% fail rate. There are about 7600 UTs so thatâs just under 900 tests that are either not running or failing. Since UTs are not great at measure real world scenarios and 900 tests is kind of a lot of tests, the UTs donât provide good validation at this point.
My plan has been to get the E2E test suite running on AspNetCore. Iâve been working on the E2E tests all week and last night I was able to get one running for AspNetCore, which is promising. However, I donât have enough of them running to get any real validation of the code.
In short, the code is written and checked in, it certainly has bugs but the total number is still a bit of a mystery. Until I clear that up, a Beta would just be an Alpha with a different name.
@robward-ms do you have plans to address #1054 and #1055 in the upcoming beta?
Specifically the #1054 it would be hard to do later.
@robward-ms great update thanks, really good to have this type of info about the development; keep up the good work guys and gals. Is there any plan on the roadmap for optimisation and performance testing with the kestrel team for TecEmpower benchmarks?
This is one of the best progress reports Iâve ever seen. Reports like this
make us deeply appreciate your effort and completely back your decision to
not release a beta quite yet.
Great job on the progress thus far.
On Sat, Dec 16, 2017 at 4:49 AM Grahame Horner notifications@github.com
wrote:
@robward-ms https://github.com/robward-ms great update thanks, really
good to have this type of info about the development; keep up the good work
guys and gals. Is there any plan on the roadmap for optimisation and
performance testing with the kestrel team for TecEmpower benchmarks?â
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/OData/WebApi/issues/939#issuecomment-352175779, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AM-qVlWWolf2tlmgeNroIV1mFZtmiVCmks5tA6BSgaJpZM4MaldT
.>
Tony Valenti
Hi,
I am trying to do some test with the package but just getting error:
`An unhandled exception occurred while processing the request.
InvalidOperationException: No service for type 'Microsoft.AspNet.OData.Formatter.Serialization.ODataSerializerProvider' has been registered.
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
Stack Query Cookies Headers
InvalidOperationException: No service for type 'Microsoft.AspNet.OData.Formatter.Serialization.ODataSerializerProvider' has been registered.
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService
Microsoft.AspNet.OData.Formatter.Serialization.ODataSerializerProviderProxy.GetODataPayloadSerializer(Type type, HttpRequest request)
Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.GetClrObjectResponsePayloadKind(Type type, bool isGenericSingleResult, Func
Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.CanWriteType(Type type, IEnumerable
Microsoft.AspNet.OData.Formatter.ODataOutputFormatter.CanWriteResult(OutputFormatterCanWriteContext context)
Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.SelectFormatterNotUsingContentType(OutputFormatterWriteContext formatterContext, IList
Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.SelectFormatter(OutputFormatterWriteContext formatterContext, MediaTypeCollection contentTypes, IList
Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.ExecuteAsync(ActionContext context, ObjectResult result)
Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+
Show raw exception details
System.InvalidOperationException: No service for type 'Microsoft.AspNet.OData.Formatter.Serialization.ODataSerializerProvider' has been registered.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredServiceT
at Microsoft.AspNet.OData.Formatter.Serialization.ODataSerializerProviderProxy.GetODataPayloadSerializer(Type type, HttpRequest request)
at Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.GetClrObjectResponsePayloadKind(Type type, Boolean isGenericSingleResult, Func`2 getODataPayloadSerializer)
at Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.CanWriteType(Type type, IEnumerable1 payloadKinds, Boolean isGenericSingleResult, IWebApiRequestMessage internalRequest, Func2 getODataPayloadSerializer)
at Microsoft.AspNet.OData.Formatter.ODataOutputFormatter.CanWriteResult(OutputFormatterCanWriteContext context)
at Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.SelectFormatterNotUsingContentType(OutputFormatterWriteContext formatterContext, IList`1 formatters)
at Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.SelectFormatter(OutputFormatterWriteContext formatterContext, MediaTypeCollection contentTypes, IList`1 formatters)
at Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.ExecuteAsync(ActionContext context, ObjectResult result)
at Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.
What I am missing?
Carmel
@carmelhl - Do you have this in your startup class?
public void ConfigureServices(IServiceCollection services)
{
services.AddOData();
}
The E2E test are running with a ~75% pass rate. I'm seeing a handful of test problems and I'm going to continue spending the day looks for product issues in there. As long as I don't find any major problems that cannot be addressed in time, I expect I'll publish a beta package tomorrow. The batching implementation is not yet complete so this will likely be the first of 2 betas.
@raffaeler - No plans to address #1054 and #1055 in the first beta.
@robward-ms thanks for your response, yes I do have:
`using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNet.OData.Extensions;
using Microsoft.AspNet.OData.Builder;
using Microsoft.OData.Edm;
using AspNetCoreODataSample2.Domain;
namespace AspNetCoreODataSample2
{
public class Startup
{
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
builder.EntitySet
return builder.GetEdmModel();
}
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddOData();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
IEdmModel model = GetEdmModel(app.ApplicationServices);
app.UseMvc(routeBuilder => routeBuilder.MapODataServiceRoute("odata", "odata", model));
}
}
}
`
@carmelhl - I don't think you are missing anything, I think you found a bug. Could you file an issue wit this info?
Also, please include the request you are sending to your service.
I can see form the stack trace that the service container, which is specific to the request, being used during formatting is missing a server that MapODataRoute will configure but it's not being found in your case, hence I'd like to understand the url causing the issue.
This is happening on the project startup, the default URL is: http://localhost:8398/api/values
When I browse to the odata url:
http://localhost:8398/odata/orders or http://localhost:8398/odata/orders(1), I receive 404.
@carmelhl - Sounds like 2 errors then: 500 & this exception on api/values, 404 on odata/orders?
Please open an issue and include the controller code as well please.
@carmelhl its just a typo. your model says Order and your url is orders either add s and lowercase your model or use Order in url. like http://localhost:8398/odata/Order
Thanks @JanEggers I fixed the Typo, I have the same issue now all urls returns: the error that i posted first time.
@carmelhl - I did run across that error about an hour ago, it's caused by the OData formatter attempting to handle a non-OData route. I'll be adding a fix for it today.
However, the fix won't necessarily fix your issue; it still indicates that the OData request, i.e. http://localhost:8398/odata/orders or http://localhost:8398/odata/orders(1), are being considered non-OData requests. The advice for that is to double-check the request Url and paramaters in MapODataServiceRoute.
Thanks @robward-ms, @JanEggers feedback about the Typo fixed fixed the issue ONLY when I remove the web api Controller, If I keep it, I receive the same error for all controller.
Hi,
I've download latest of alpha version and OData parameters still not work properly.
My Sample action method (CustomerRoleInsertAction) in ODatacontroller looks like this:
[HttpPost]
public IActionResult CustomerRoleInsertAction([FromBody] int customerId, [FromBody] int customerRoleId)
{
return Ok(1);
}
When I run this action by OData client, field customerId always has 0. Request contains Body: {"customerId":6,"customerRoleId":6} and the action is run in the controller, but without correct paremeters.
Thanks for any suggestions.
@KrzysztofPajak - You have two parameters with FromBody specified. From the docs: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding
There can be at most one parameter per action decorated with [FromBody]. The ASP.NET Core MVC run-time delegates the responsibility of reading the request stream to the formatter. Once the request stream is read for a parameter, it's generally not possible to read the request stream again for binding other [FromBody] parameters.
Maybe you mean to bind these to form values instead? Adding FromBody tells AspNetCore to only get them from the body.
@robward-ms
I used model and it works perfectly. Great, thank you for your help!
The E2E test are now running with a ~85% pass rate. I'm still seeing a handful of test problems and failures on negative test cases but all major scenarios have passing tests, only batching and using query outside of non-OData routes appear to have issues. The issues I did find were fixed in #1173 which was merged this morning.
First off, thanks to everyone for your patience. I know itâs taken a while to get here. Second, thanks to everyone who downloaded and provided feedback on the Alpha/nightly packages.
Iâm happy to announce the Beta1 release of Web API OData for ASP.NET and ASP.NET Core. You can find the release notes here: http://odata.github.io/WebApi/#14-01-netcore-beta1
And youâll find the package here: https://www.nuget.org/packages/Microsoft.AspNetCore.OData/
If you find issues, please file them here on GitHub and add the [feature/netcore] tag.
And to @AlexanderBatista, if you send me your address, Iâll send you a toaster for having the closest guess for the release date.
@robward-ms
Beta and Latest version of OData caused problem:
ArgumentNullException: Value cannot be null.
Parameter name: routeName
My previouse version of OData library was 7.0.0-Nightly201712201325 and works properly.
After update to version 7.0.0-Nightly201712212331 I've got error:
ArgumentNullException: Value cannot be null.
Parameter name: routeName
The error comes from the library: Microsoft.AspNetCore.OData
@KrzysztofPajak - Thanks, looks like it's the issue tracked in #1175.
@KrzysztofPajak - Yep, it's a new issue that was caused by a last minute change. It occurs when a request is made on a non-OData route, which your project is configured to open (look in project properties, debug, app URL for the default URL). If you make a request against the configured OData endpoint, it should work as expected.
You can work around this issue by adding the following inside the UseMvc lambda, right below the call to MapODataServiceRoute():
routes.EnableDependencyInjection();
Where routes is the name of the IRouteBuilder lambda parameter.
@robward-ms
Thanks, it works!
Is there a version of Restier that will work with this in an Asp.net Core solution? If not, any suggestion as to when something could be expected?
@radicalapps - Sorry, no version of RESTier to go with this. I don't have an ETA.
@robward-ms @radicalapps I'm going to be working this week on a Classic ASP.NET build of Restier that works with WebAPI OData 7.0, but no promises on ETA or Core support.
Rob, once you get to Restier, I'd really like to do a Skype chat with you about the changes I've been thinking about/working on for Restier 1.0. Thanks, and Merry Christmas everyone!
@robward-ms
It looks like no matter how I try, I cannot filter using the $filter operator.
I'm always getting this meesage:
"The query specified in the URI is not valid. The property 'Url' cannot be used in the $filter query option."
I made sure a 'Url' property is indeed in the model, and even tried different casing.
What I tried so far, without success:
But still, it doesn't work...
What am I missing?
@memilavi - Could you open an issue and provide some startup, controller and request URL details?
@robertmclaws - Just to be clear, you are planning on grabbing the Nightly version of Microsoft.AspNet.OData v 7.0 and integrating that with RESTier?
I tried to make sure it was a namespace replace only. I'd love some feedback on your experience here. Hopefully it's a search/replace on the using's and if you have StyleCop enabled where the namespace's need to be sorted, there are a few VS extensions that can be added via the gallery to sort all using's in a project.
@robward-ms Just did! https://github.com/OData/WebApi/issues/1179
@robward-ms
Thank you for the superb turnaround with OData support for ASP.Net Core support. Overall it works exceptionally well, however it seems like I'm unable to make use of $skip to perform paging operations.
When I use $skip in the odata request, the response has an abrupt end as follows:
{"@odata.context":"http://localhost:15004/odata/$metadata#ActivityTypes","@odata.count":4,"value":[
Has anyone here run into similar issues? Or am I using the wrong operator?
The full Request uri: http://localhost:15004/odata/ActivityTypes/?$top=2&$skip=0&$count=true
Update: @robward-ms - Please ignore this. The issue was not related to OData or its configurations. (See my comment below, fifth down from this one)
@msalmank in total agreement @robward-ms has done a fantastic job and totally deserves acknowledgement from the community with regards to this work. @msalmank with regards to the $skip=0 what is the result if you omit the skip parameter?
@robward-ms Q: if have a use case where I wish to use the same odata schema with multiple data source; is it at all possible to pre-fix the odata path with a value which then can be used to determine which data source to use? eg: /source1/odata/.... /source2/odata/....
@grahamehorner If i exclude $skip, it works without issues. But I intend on using it to perform paging using OData. So I could have the following: $top=5&$skip=10 to get the top 5 after skipping the first 10 records.
@msalmank yes, that what I also do; what happens if the $skip=0 is a positive number greater than 0 ?
@grahamehorner $skip with any value (0 or greater) is resulting in the same response, with the value being stripped off after the array start.
Is it working properly for you? I may not have a specific configuration set perhaps.
Update: I just created a test project and enabled OData on it and, surprisingly, $skip is working as expected on it. So now, off I go to try and figure out what may have been missed across the projects. It would have to be something very specific, as all configurations across the projects are same.
Update 2: Okay, so as it turned out, the issue was not related to OData or its configurations at all but had to do with EF Core being used against SQL 2008 R2 (Client Minimal Requirements) and needed to have the DataContext configured to Use Row Number for Paging. :)
All - Sorry for the long silence (again), I've been heads down (mostly banging it on the desk) working through the E2E test framework, simplifying it ALOT (now one project) and getting it to run reliably. As of today, I was able to get that in review, see #1229.
There are quite a few bugs piling up and I've not worked on most of them, mainly because the tests for Net Core are not checked in yet. I ran them locally before the Beta to get enough confidence for release but it was a bit of a custom setup. I would rather get some (all!) of those tests checked in and use the tests to validate product fixes for the bugs you have found.
Getting the E2E suite for AspNet (non-core) running on XUnit 2 (to allow them to compile for AspNetCore as well) was step 1. Now that's done, I can begin to rebase my existing test work on top of a valid (and simplified) framework and get some (all!) checked in.
Next steps: add Net Core Tests, test batching (it's coded & in my fork) and fix some bugs, then Beta2.
Thanks again for your patience and thanks for trying out the Beta and providing feedback. - R
@robward-ms I had to stop my tests because of the breaking changes this new version introduces.
Basically I need to convert the odata string into an expression without webapi. It worked with the past version, but now the DI requires objects that comes from internal classes and I am stuck.
Do I have any hope or I should abandon the project and build my own parser? I hope not because parsers are always a source of trouble....
@raffaeler - I don't think you need to abandon your project just yet, I have a few comments on #1218 and #1219 that I think could and should be resolved for the next Beta. If you have issues beyond those two, please let us know/file an issue.
All - with the exception of issue 1154 from @techniq, 1204 from @genusP, and 1175 from @gordon-matt, I think I have looked at and commented all on reported issues. If there is an issue you filed that has not received a comment and/or is marked with "in-progress", please let me know. Thanks - R
@robward-ms Thanks for all the hard work on this. I just want to add that issue #1233 is yet to be addressed, but it's relatively new (14 hours old)
Hi. I am trying to run a simple example with odata with net core 2 on linux x64. What is wrong?
$dotnet --version
2.1.4
$dotnet new webapi -o example_webapi_odata
$cd example_webapi_odata
$dotnet add package Microsoft.AspNetCore.OData --version 7.0.0-beta1
$ cat Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.OData.Extensions; // new line
namespace example_webapi_odata
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
$ cat example_webapi_odata.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.0.0-beta1" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
</ItemGroup>
</Project>
md5-fe25aa8ce72df3ceae74b3141d6988bc
$ dotnet build
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 107.68 ms for /opt/microsoft/projects/example_webapi_odata/example_webapi_odata.csproj.
Restore completed in 60.86 ms for /opt/microsoft/projects/example_webapi_odata/example_webapi_odata.csproj.
Startup.cs(11,28): error CS0234: The type or namespace name 'OData' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?) [/opt/microsoft/projects/example_webapi_odata/example_webapi_odata.csproj]
Build FAILED.
Startup.cs(11,28): error CS0234: The type or namespace name 'OData' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?) [/opt/microsoft/projects/example_webapi_odata/example_webapi_odata.csproj]
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:06.79
@superriva, namespace for Odata Lib:
Microsoft.AspNet.OData
@superriva
using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNet.OData.Extensions;
@superriva Change your using statement from
using Microsoft.AspNetCore.OData.Extensions; to using Microsoft.AspNet.OData.Extensions;. Same with Builder.
@superriva just an fyi, we have a sample w/ ASP.NET Core w/ OData working on all OS/environments https://github.com/urfnet/URF.Core.Sample. We are using the myget nightly OData NuGet package as of last night.
I did it with example code from http://odata.github.io/WebApi/#11-01-OData-V4-Web-API-Scaffolding (section "14.1 7.x Beta1") both on Windows and Linux platform. I apologize. The driver Microsoft.AspNetCore.OData v7.0.0-beta1 works.
First off - thanks for everyone's effort on this project! I'm wondering if the OData preview stuff here is included in the .NetCore 2.1 preview that was released a couple of days ago? Or is this completely separate from what is going on in the NetCore project?
@SimplerSoftware - It's separate.
I'm having a challenge unit testing controller methods that take ODataQueryOptions as a parameter. Any samples showing how to do this?
Also, is there a time frame for the next nuget package release?
@Andrew-Laughlin - If you need to create a ODataQueryOptions, take a look at the AspNetCore UTs, for which I just submitted the PR. Take a look at #1261, testUnitTestMicrosoft.Test.AspNet.ODataQueryODataQueryOptionParserExtensionTest, lines 90 to 110.
To answer @andrew-laughlin question on timeframe, I just released Beta 2. You can find it here: https://www.nuget.org/packages/Microsoft.AspNetCore.OData/
Thanks so much for this @robward-ms.
I just pulled the beta2 nuget and was looking at the reference page, however in e. Configure the OData Endpoint it mentions using Register(HttpConfiguration config) to declare the entities and build the routing from it.
Isn't this the way .Net __Framework__ Web API works? I was expecting some extension method for IApplicationBuilder to bootstrap like .Net __Core__ ASP.Net apps do.
Am I missing something? Can someone specify how to configure this in ASP.Net core with the available methods when creating a project with dotnet new webapi? i.e.:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
@grumpydev-net You need to do something like the following:
var edmModel = GetEdmModel(app.ApplicationServices);
app.UseMvc(routes =>
{
// Enable all OData functions
routes.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
routes.MapODataServiceRoute("OData", "odata", edmModel);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
builder.EntitySet<MyEntity>("MyEntities");
return builder.GetEdmModel();
}
@grumpydev-net full source code and ASP.NET Core w/ OData Core configuration https://github.com/urfnet/URF.Core.Sample with live demo link. Have tested the exact configuration for both the previous Asp.Net.Core.OData (initial beta) as well as the current one (just released).
@grumpydev-net - Are you looking at this section of the docs? In that section, the configure method takes an IApplicationBuilder:
public void Configure(IApplicationBuilder app)
{
...
}
Thanks @robward-ms, @lelong37 and @gordon-matt for the help! I was able to build and run the example! :) I think the ASP.NET Core setup should be more a 1st class citizen in the documentation.
So anyways, I'm starting a POC next week so I can offer a lot of testing. I'll log any issue here unless you want me to reach on Skype or Teams. But its Friday PM now and its beautiful outside, so Cheers for now!
@robward-ms Can you tag the releases, so it is easier to find which commit that has been published in different releases? Found a tag for beta 1 but none for beta 2.
@dozer75 - Thanks for catching that, tag 7.0.0.B2 added.
I've been unsuccessful in implementing a create relationship method. Specifically I can't get past getting 404. Didn't see a demo method in @lelong37 's https://github.com/urfnet/URF.Core.Sample.
I created this SO - CreateRef method migrated to .Net Core results in 404, how to implement Create Relationships in OData with .Net Core.
Any input is appreciated.
Hi @robward-ms,
I just tried to model bind a posted model to EdmEntityObject (using 7.0.0-beta2) but got the following exception:
System.InvalidOperationException: Could not create an instance of type 'Microsoft.AspNet.OData.EdmEntityObject'. Model bound complex types must not be abstract or value types and must have a parameterless constructor.
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext)
(shorted)
I looked into the code and was missing the registration of OData serializer stuff. Using the non-Core version model binds perfectly. Am I missing something I have to configure to make this work, or is this part still in progress? I saw there is an internal class ODataModelBinder, but this class is not used and there is no model binder provider for it.
Cheers, Matt
@mgernand - Can you open an issue and provide your controller and configuration code as well as the URL you are posting?
@robward-ms - I created an example application. While doing this I realized that the exception only occurs if no [FromBody] attribute is annotated to the post parameter. Is this still an issue? I could create one and attach the example.
@mgernand - [FromBody] was implicit in AspNet but must be added explicitly in AspNetCore. I believe what you are seeing is expected.
@robward-ms - Great! No harm meant! Thanks for your help.
Please tell me this will be supported in .NET Core:
https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options
@stumpykilo Yes, it's already working now. Just download the preview of Microsoft.AspNetCore.OData from MyGet here: https://www.myget.org/F/webapinetcore/
Then look at This Post or others you can find here for an example.
@gordon-matt Wow! Thanks! I'm really new to OData, how do I convert/map back and forth between my models and entities? I don't want my entities exposed to the controller, only using models in that layer.
So my Get method would look like this: public IQueryable<MyModel> Get(ODataQueryOptions<MyModel> options)?
My context looks like this: public virtual DbSet<MyEntity> MyEntity { get; set; }.
@stumpykilo i did something you are looking a while ago ( https://stackoverflow.com/q/29137814/1252994 - the question )
But what you are looking is to use Projection:
IQueryable<MyEntity> entities = dbContext.MyEntity;
IQueryable<MyModel> projectedModels = entities.Select(myEntity => new MyModel() { ... });
IQueryable projectedModelsWithOptionsApplied = oDataQueryOptions.ApplyTo(projectedModels);
Take a look at AutoMapper, this lib can help too.
@jvitor83 Sweet! That works really well except for my collections. I have written custom mappers myself but get errors like:
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'orderby EntityToModel([entity], True).Id asc' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'orderby EntityToModel([entity], True).Id asc' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Skip(__TypedProperty_0)' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Skip(__TypedProperty_0)' could not be translated and will be evaluated locally.
warnwarn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Take(__TypedProperty_1)' could not be translated and will be evaluated locally.
: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Take(__TypedProperty_1)' could not be translated and will be evaluated locally.
And when I use the $expand option for one of my collections I get an error:
Value cannot be null.rnParameter name: source
When I do my projection I use my custom mapper like this:
var modelsProjected = entityQueryable.Select(entity => CustomerMapper.EntityToModel(entity, true));
@stumpykilo It seems like you are trying to do the conversion to your model on the IQueryable, which is the problem. You need to call ToList() or ToHashSet() (or similar) BEFORE trying to convert it, else the IQueryable will try to translate your EntityToModel() method as though it was a T-SQL function and that's why you get that error. The IQueryable is not actually storing any data in memory - it's just a way of building the query.. only when you call something like ToList(), then that IQueryable is translated into T-SQL and results are returned to you. So do something like this instead:
var modelsProjected = entityQueryable.ToList().Select(entity => CustomerMapper.EntityToModel(entity, true));
@stumpykilo Working with this right now
The best to do is to use AutoMapper for this, you can then return the IQueryable
In your DTO's for collections use IEnumerable
Don't forget to register the rules for your DTO in the odata model builder.
Thanks @gordon-matt and @dozer75!
@gordon-matt I don't think I want to materialize my queryable at that point because it will run the query before I've applied my options (does that sound right??). I should have included my entire controller method to give some better context. This is pretty much exactly like @jvitor83's solution in his StackOverflow question he mentions above:
```c#
[EnableQuery]
public IQueryable
{
//_context.Customer is of type CustomerEntity
var entityQueryable = _context.Customer.AsQueryable();
var modelsProjected = entityQueryable.Select(entity => CustomerMapper.EntityToModel(entity, true));
IQueryable modelsWithOptionsApplied = options.ApplyTo(modelsProjected);
IQueryable<CustomerModel> modelsToExecute = modelsWithOptionsApplied as IQueryable<CustomerModel>;
ICollection<CustomerModel> modelsExecuted = modelsToExecute.ToList();
return modelsExecuted.AsQueryable();
}
```
I think I'm going to see about using AutoMapper instead of my own EntityToModel method.
@dozer75 I'm using ICollection for my collections, should be fine, right? Also, could you provide some examples on the registering rules for my DTO in the odata model builder? Not sure what you mean.
@stumpykilo Don't use both the [EnableQuery] attribute and the options.ApplyTo() method. They basically do the same thing and I ran into a bug when using both together (some options get applied twice. For example: $skip). You can read more about that bug here if you want. Anyway, if you go with the options.ApplyTo() then I don't see a problem. Just apply your options to your IQueryable first and then materialize them after. For example:
var query = context.Customers; // This would be an IQueryable<Customer>
var results = options.ApplyTo(query); // results is just a non-generic IQueryable
Then do something like:
var models = (results as IQueryable<Customer>).ToList().Select(x => CustomerMapper.EntityToModel(x, true))
Note: Replace EntityToModel() with the Mapper.Map() function if using AutoMapper. Also, I haven't tested this, but it should work, since you would be applying your options before materializing the results, just as you want... and then convert the results to models.
@gordon-matt I can't apply OdataQueryOptions<CustomerModel>to IQueryable<CustomerEntity>, that is what I'm trying to solve. I don't want to have my method signature on my controller to be:
public IQueryable<CustomerEntity> Get(ODataQueryOptions<CustomerEntity> options).
I want it to be:
public IQueryable<CustomerModel> Get(ODataQueryOptions<CustomerModel> options).
My Get method (from above) works (kind of) if I don't use the $expand, I can successfully get back 10 CustomerModel records (even though the sql generated queries for all customers - see below) with no collections. But when I use the $expand for one of my collections the modelsToExecute becomes null and therefore my modelsToExecute.ToList() fails.
Another interesting thing I've noticed is if I do the simple method with CustomerEntity like this:
[EnableQuery]
public IQueryable<CustomerEntity> Get()
{
return _context.Customer.AsQueryable();
}
The sql that it generates is correct, I'm using $top=10&$skip=10 to test this and it only fetches for the 10 records. But when I go the other route and apply the options myself (with or without the [EnableQuery] attribute) it grabs ALL records and then applies the filter and returns the 10 records. I don't want the sql to go and get ALL records, just the 10.
@stumpykilo Well, I use IEnumerable since I don't need any modifications of the collections in my DTO, I haven't actually tried ICollection if it works (it didn't work in earlier versions of EF generally, maybe it works now).
As @gordon-matt says, don't use EnableQuery and ApplyTo together, this will only confuse the framework and cause problems. EnableQuery will do the modification of your projected IQueryable after returning from the controller.
Let me give you a simple example here on how I do it:
First, the EF entities:
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Registered { get; set; }
public string Creator { get; set; }
public List<Contact> Contacts { get; set; }
public Customer()
{
Contacts = new List<Contact>();
}
}
Then DTOs:
public class ContactDTO
{
public string Name { get; set; }
}
public class CustomerDTO
{
public string Name { get; set; }
public DateTime Registered { get; set; }
public IEnumerable<ContactDTO> Contacts { get; set; }
}
The AutoMapper config:
MapperConfiguration cfg = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Contact, ContactDTO>();
cfg.CreateMap<Customer, CustomerDTO>();
});
And finally the controller:
[EnableQuery]
[HttpGet]
public IQueryable<CustomerDTO> Get()
{
return context.Customers.ProjectTo<CustomerDTO>(cfg);
}
And that's it.
Any query you'll throw against this controller will do all mapping magic for you, return a IQueryable to the OData layer which will append the filters, selects, orderbys and all other functions OData supports to your IQueryable and execute it.
If you for example will filter on registered you'll just pass in $filter=Registered gt <the date> and OData will append this to the IQueryable as you would have done .Where(dto => dto.Registered > <the date>).
You can even do some pre and postfiltering on your IQueryable before returning to limit.
Example if you want to limit to only the ones created by a logged in user like this
return context.Customers.Where(customer => customer.Creator == context.User.UserName).ProjectTo<CustomerDTO>(cfg);
everyone that calls this OData query will be limited to their own customers.
This example just surfacing the possibilities, but I think that AutoMapper and OData really fills each other out.
@dozer75 Thanks, I've made some changes according to your recommendations. Let me see if I can document in here what I have.
My controller method:
[EnableQuery]
[HttpGet]
public IQueryable<CustomerModel> Get()
{
return _context.Customer.ProjectTo<CustomerModel>();
}
My mapping profile:
public MappingProfile()
{
CreateMap<CustomerEntity, CustomerModel>();
CreateMap<CustomerAddressEntity, CustomerAddressModel>();
CreateMap<CustomerChangeEntity, CustomerChangeModel>();
CreateMap<CustomerGroupMemberEntity, CustomerGroupMemberModel>();
CreateMap<CustomerNoteEntity, CustomerNoteModel>();
CreateMap<CustomerPreferenceEntity, CustomerPreferenceModel>();
}
My route config in Startup.cs:
var edmModel = GetEdmModel(app.ApplicationServices);
app.UseMvc(routes =>
{
routes.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
routes.MapODataServiceRoute("OData", "odata", edmModel);
routes.EnableDependencyInjection();
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
And my GetEdmModel method also in Startup.cs:
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
builder.EntitySet<CustomerModel>("Customers");
builder.EntitySet<CustomerAddressModel>("CustomerAddresses");
return builder.GetEdmModel();
}
I also changed my CustomerModel to have IEnumerable for its children. When I run "Customer?$top=10&$skip=10" in Postman I get the following errors in my console window:
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'orderby new CustomerModel() {Guid = [dto].Guid, LocationId = [dto].LocationId, SalesPersonId = [dto].SalesPersonId, SalesTaxId = [dto].SalesTaxId, PictureId = [dto].PictureId, StyleTaxId = [dto].StyleTaxId, LastName = [dto].LastName, FirstName = [dto].FirstName, Company = [dto].Company, Company2 = [dto].Company2, Points = [dto].Points, Balance = [dto].Balance, CreditLimit = [dto].CreditLimit, AlertMessage = [dto].AlertMessage, Website = [dto].Website, Classification = [dto].Classification, EmployeeLogin = [dto].EmployeeLogin, Birthday = [dto].Birthday, CustomerSince = [dto].CustomerSince, LastUpdated = [dto].LastUpdated, Global = [dto].Global, Alert = [dto].Alert, NotTaxable = [dto].NotTaxable, International = [dto].International, BadAddress = [dto].BadAddress, OptOut = [dto].OptOut, WholeSale = [dto].WholeSale, NoDiscounts = [dto].NoDiscounts, DoNotCall = [dto].DoNotCall, DoNotEmail = [dto].DoNotEmail, Addresses = {from CustomerAddressEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerAddressEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerAddressModel() {Guid = [dto].Guid, CustomerId = [dto].CustomerId, StyleTaxId = [dto].StyleTaxId, SalutationId = [dto].SalutationId, AddressName = [dto].AddressName, Company = [dto].Company, Address1 = [dto].Address1, Address2 = [dto].Address2, PrimaryShipping = [dto].PrimaryShipping, PrimaryBilling = [dto].PrimaryBilling, ZipCode = [dto].ZipCode, City = [dto].City, County = [dto].County, State = [dto].State, Country = [dto].Country, Phone = [dto].Phone, Id = [dto].Id}}.ToList(), Changes = {from CustomerChangeEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerChangeEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerChangeModel() {CustomerId = [dto].CustomerId, ChangeDate = [dto].ChangeDate, Change = [dto].Change, Id = [dto].Id}}.ToList(), GroupMembers = {from CustomerGroupMemberEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerGroupMemberEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerGroupMemberModel() {CustomerId = [dto].CustomerId, ExpirationDate = [dto].ExpirationDate, Id = [dto].Id}}.ToList(), Notes = {from CustomerNoteEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerNoteEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerNoteModel() {CustomerId = [dto].CustomerId, Note = [dto].Note, Id = [dto].Id}}.ToList(), Preferences = {from CustomerPreferenceEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerPreferenceEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerPreferenceModel() {PreferenceId = [dto].PreferenceId, Preference = [dto].Preference, CustomerId = [dto].CustomerId, Additional = [dto].Additional, Other = [dto].Other, Id = [dto].Id}}.ToList(), Id = [dto].Id}.Id asc' could not be translated and will be evaluated locally. warn: Microsoft.EntityFrameworkCore.Query[20500] The LINQ expression 'orderby new CustomerModel() {Guid = [dto].Guid, LocationId = [dto].LocationId, SalesPersonId = [dto].SalesPersonId, SalesTaxId = [dto].SalesTaxId, PictureId = [dto].PictureId, StyleTaxId = [dto].StyleTaxId, LastName = [dto].LastName, FirstName = [dto].FirstName, Company = [dto].Company, Company2 = [dto].Company2, Points = [dto].Points, Balance = [dto].Balance, CreditLimit = [dto].CreditLimit, AlertMessage = [dto].AlertMessage, Website = [dto].Website, Classification = [dto].Classification, EmployeeLogin = [dto].EmployeeLogin, Birthday = [dto].Birthday, CustomerSince = [dto].CustomerSince, LastUpdated = [dto].LastUpdated, Global = [dto].Global, Alert = [dto].Alert, NotTaxable = [dto].NotTaxable, International = [dto].International, BadAddress = [dto].BadAddress, OptOut = [dto].OptOut, WholeSale = [dto].WholeSale, NoDiscounts = [dto].NoDiscounts, DoNotCall = [dto].DoNotCall, DoNotEmail = [dto].DoNotEmail, Addresses = {from CustomerAddressEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerAddressEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerAddressModel() {Guid = [dto].Guid, CustomerId = [dto].CustomerId, StyleTaxId = [dto].StyleTaxId, SalutationId = [dto].SalutationId, AddressName = [dto].AddressName, Company = [dto].Company, Address1 = [dto].Address1, Address2 = [dto].Address2, PrimaryShipping = [dto].PrimaryShipping, PrimaryBilling = [dto].PrimaryBilling, ZipCode = [dto].ZipCode, City = [dto].City, County = [dto].County, State = [dto].State, Country = [dto].Country, Phone = [dto].Phone, Id = [dto].Id}}.ToList(), Changes = {from CustomerChangeEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerChangeEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerChangeModel() {CustomerId = [dto].CustomerId, ChangeDate = [dto].ChangeDate, Change = [dto].Change, Id = [dto].Id}}.ToList(), GroupMembers = {from CustomerGroupMemberEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerGroupMemberEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerGroupMemberModel() {CustomerId = [dto].CustomerId, ExpirationDate = [dto].ExpirationDate, Id = [dto].Id}}.ToList(), Notes = {from CustomerNoteEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerNoteEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerNoteModel() {CustomerId = [dto].CustomerId, Note = [dto].Note, Id = [dto].Id}}.ToList(), Preferences = {from CustomerPreferenceEntity dto in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[mPower.Contracts.Customer.Entities.CustomerPreferenceEntity]) where Property([dto], "Id") ?= Property([dto], "CustomerId") select new CustomerPreferenceModel() {PreferenceId = [dto].PreferenceId, Preference = [dto].Preference, CustomerId = [dto].CustomerId, Additional = [dto].Additional, Other = [dto].Other, Id = [dto].Id}}.ToList(), Id = [dto].Id}.Id asc' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Skip(__TypedProperty_0)' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Skip(__TypedProperty_0)' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Take(__TypedProperty_1)' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Take(__TypedProperty_1)' could not be translated and will be evaluated locally.
And then I notice in SQL Profiler that its querying everything including all my children for 7k customers so that takes a while. What am I doing wrong? When I wire it up with CustomerEntity, all good. It's only when I try using with CustomerModel that it behaves this way.
Ok, wow, sorry guys. I was deriving from an abstract class for all my models. Once I removed that and put the property on the models themselves it started working.
So now by default when I run the "Customer?$top=10&$skip=10" it fetches 10 and returns 10 but it automatically gets all the children. Is there a configuration to make it not do that by default? I only want the children I specify in $expand to get fetched.
Sorry again y'all and thanks so much for all the suggestions/answers/recommendations!
Strange, I use an abstract DTO for base properties, can't see why it shouldn't work for you. However, remember that top and skip requires an ordered query, according to your dump it seems that you don't have that (it tries to sort on the DTO itself)? Have you tried to send down an $orderby?
As for your expand problem, I don't recall having that issue either, I don't my usage here but I see you have configured Expand() (don't remember what that config does if it allows expand or triggers default expand), try to remove that and see.
**Edit:
Just tested now and I don't get them expanded automatically, can't really see why you get it either, your code looks similar to me (including the Expand), only difference is the IEnumerable/ICollection usage, could it be that?
@dozer75 I can't get the $expand to work, its always getting back all children. Is that not the behavior you see? I think AutoMapper does this with .ProjectTo. I can use the ExplicitExpansion option on my map but that doesn't seem to work well when I ApplyTo and use ProjectTo.
Well... i make some research and this is what i found (about Expand, GroupBy and Aggregate) with version odata-beta2 and ef-2.1:
public IActionResult Get(ODataQueryOptions<Models.Blog> oDataQueryOptions)
{
////Checking that EF does works with groupby (EF 2.1)
//var checkThatGroupByWorksAtEFCore = this.BloggingContext.Blogs.GroupBy(r => r.BlogId).ToList();
IQueryable<Data.Blog> blogsData = this.BloggingContext.Blogs;
////Using AUTOMAPPER (with ExplicitExpansion): Expansion, GroupBy and Aggregate DON'T works
//var includes = (oDataQueryOptions?.SelectExpand?.RawExpand?.Replace('/', '.')?.Split(',') ?? new string[] { });
//IQueryable<Models.Blog> blogsApi = blogsData.ProjectTo<Models.Blog>(this.Mapper.ConfigurationProvider, null, includes);
////Using SELECT: Expansion Works but no GroupBy and Aggregate
IQueryable<Models.Blog> blogsApi = blogsData.Select(r => new Models.Blog()
{
BlogId = r.BlogId,
Url = r.Url,
Posts = r.Posts.Select(p => new Models.Post()
{
PostId = p.PostId,
BlogId = p.BlogId,
Title = p.Title,
Content = p.Content,
})
});
////If i execute here: Expand, GroupBy and Aggregate works
////(but it shouldn't be required since it must apply the options at database, otherwise it will bring all data in memory to apply the ODataQueryOptions)
//blogsApi = blogsApi.ToList().AsQueryable();
IQueryable blogsTransformed = oDataQueryOptions.ApplyTo(blogsApi);
////This return (without execute): generate the `@odata.context` and `value` at json
return Ok(blogsTransformed);
////This return (by executing the iqueryable): generate the json only with the result (without the `@odata.context` metadata and `value`)
//IQueryable<object> blogsToExecute = blogsTransformed as IQueryable<object>;
//var executed = blogsToExecute.ToList();
//return this.Ok(executed);
}
The Project used is here -> https://github.com/jvitor83/OData-Core-Tests
The Requests:
I confirmed that what @jvitor83 documented works, just using the normal projection using Select:
////Using SELECT: Expansion Works but no GroupBy and Aggregate
IQueryable<Models.Blog> blogsApi = blogsData.Select(r => new Models.Blog()
{
BlogId = r.BlogId,
Url = r.Url,
Posts = r.Posts.Select(p => new Models.Post()
{
PostId = p.PostId,
BlogId = p.BlogId,
Title = p.Title,
Content = p.Content,
})
});
I'd really prefer not to have this type of mapping done in my controllers and ProjectTo with AutoMapper seems to return back all collections regardless of options (not ideal either). Are there alternatives to putting this type of mapping code somewhere else? I tried using my own custom mapper but I get linq errors when it goes to evaluate.
I do still get warnings when I submit a request like this:
Customer?$filter=FirstName eq 'Rick'&$expand=Addresses&orderby=LastName
Warnings will show up in my console window but I'm getting the results I'm expecting:
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'orderby new CustomerAddressModel() ... }.Id asc' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Take(__TypedProperty_1)' could not be translated and will be evaluated locally.
@stumpykilo Try to use IEnumerable<> and ProjectTo<>(), see what happens, that is the difference between your code there and mine. AutoMapper generates a Select that uses ToList() for the collection if you use ICollection<>, it could be that that causes your auto expand.
@dozer75 I am no longer using ICollection<> for my children, I'm using IEnumerable<> everywhere in my models and List<> in my entities.
@ttugates - Sorry for the delay. ODataActionSelector had a bug where it was too aggressive in picking a signature even it could not fulfill all bindings, which did affect Ref routing. I filed #1365, created PR #1366 and Sam merged it.
Can you try a nightly build and see if the issue is resolved?
@robward-ms - We decided to move forward on our project without OData so am not in a position to duplicate. Al the same thanks for update and look forward to Release :)
@robward-ms
Hi Rob,
I consider to integrate the Odata aspnetcore implementation to my project.
I would like to know If you have a release date for a stable version of the Microsoft.AspNetCore.Odata Nuget package?
Thank you,
Olivier
@OlivierDeRivoyre - I'm going to let @xuzhg answer this question.
@OlivierDeRivoyre and @all: Thanks for questions about the stable version. We are trying our best to release a version with: 1) bugs as less as possible 2) features as much as possible to fill the gaps between ODL. So, It still need more times because of no only resource changed, but also more tasks left. We'd like to release a new beta version in the coming weeks. After that, It should be a 7.0.0 RTM. I think, only in my opinion, It maybe happen in couple months.
Thank you Rob & Sam for your quick answer.
@xuzhg , the .net core and asp.net core 2.1 is now in preview2-final and are about to release in 2 or 3 months, is it possible to align the 7.0.0 RTM release schedule with that?
Good to hear there will be a beta version coming out soon, we'd like to try that after it's released.
Actually yesterday MS release dotnet core 2.1 Rc1 with GoLive. Starting to use it next week - and desperately in need of an odata server component asap for 2 projects.
@chuanboz @NetTecture Would you please share us the reasons "have to update to 2.1 or high"?
Simple. Entity Framework 2.1 - 2.0 is unusable for us thanks to missing Group By.
This is a long term project and I am opening an evaluaton branch for 2.1. We are getting a go for a refactoring of a quite old and convoluted codebase and given a 12 month timeframe I am really not planning to go with full dotnet.
On top, 2.1 does actually have a golive license,
Sad how - sadly - Odata is now the stepchild of the whole dotnet web stack.
EF2.1 does support group by:
https://blogs.msdn.microsoft.com/dotnet/2018/02/27/announcing-entity-framework-core-2-1-preview-1/
Please please please read what I said again and then have someone explain it to you. You obviously misunderstand plain english.
Yes, 2.1 does group by - this is why we need to use 2.1 and can not use 2.0.
Sadly 2.1 has no odata release yet ;(
You should read again what you said instead of complaining.
What I really don't understand is your rudeness towards people that is only willing to help.
Ah, please. Rude is... misunderstanding...
"Simple. Entity Framework 2.1 - 2.0 is unusable for us thanks to missing Group By."
A little more complex english than in comic books. The answer to:
"Would you please share us the reasons "have to update to 2.1 or high"?"
Simple. EF 2.1
2.0 is unusable for us thanks to missing GroupBy.
It is quite easy to understand (once you get over the SJW attitude of yours) that missing group by refers to 2.0, not 2.1
"What I really don't understand is your rudeness towards people that is only willing to help."
"An gutem willen geht die Welt zugrunde."
Have someone translate that for you. And explain it, likely. I generally give zero credit for trying. I also do not get paid for tryiing.
And I stand to is - sadly OData is the stepshild of the whole stack. Damn, it is such a nice technology but it seems to fall wayside in implementation at the moment.
@NetTecture - Sorry you feel that OData is not adequate for your project. Also, I've met @raffaeler and he's well spoken and understands English pretty well.
All,
I've updated the Code of Conduct in the README.md to reflect the Microsoft Open Source Code of Conduct. You can review it here.
Says tthe next person. I don't think that OData is not adequate - in fact, I think OData is probably the best solution for a very crappy problem that anyone so far has come up with. But OData is a piece of paper - a specification. Andit was repeatedly communiated tha this project is behind schedule with ressources being pulled left and right. That IS the definition of a stepchild project - something falling on the wayside of ressources If it would not be a stepchild project you would have all the ressources and have a beta or something out these days on the nuget official feed to support the dotnetcore 2.1 release. Including client code generation. The fact that OData in dotnet core is like permanently late and that for example Alan Wong has posted stuff like "as our resources were being pulled left and right during the past months." totally makes it a stepchild project.
I have never said OData is not adequate. It has some "issues", spec wise, but nothing too grave, particularly in the lst release (how anyone could not have an IN verb for select originally is something I can only attribute to... well, yeah, not thinking it through - but that is fixed now.
Frankly, I am quite a little afraid about the future of Odata - because MS has a LONG history of abandoning projects exactly in this area, and so far Odata is about the best thing I have seen to this particular problem.. Funny for example how I am watching build conference videos now and there seems to be zero information about a common data access standard between program parts (i.e. Odata). While this is pretty much extremely important.
And btw., I follow the code of conduct. not in the US "SJW and everyone can complain about being insulted" way, but in the good old german "stand to your facts and be right" way. Yeah, cultural difference.
@NetTecture - The code of conduct is explicit, please read and abide by it. Again, you can review it here.
All opinions are welcome and we value constructive conversations. However, your tone is aggresive and insulting.
You are right. That definitly invalidates every argument I ever made. Robert. Better not make arguments at all because they are insulting to you. Quite understood. Have a good night.
Would you please share us the reasons "have to update to 2.1 or high"?
@xuzhg , the reason we target asp.net core 2.1 is because of the extensive support on [Generic Host] (https://github.com/aspnet/Hosting/issues/1163) and DI and other Microsoft.Extensions.* package that give us flexibility and productivity.
Ideally, I'd like to see OData .net core support to natively have the DI support. For example, provide the ability to integrate with IHttpClientFactory to allow us to customize the HttpClient used for communication, that will further allow us to integrate it with Polly library for retry, and also better integrate with Service Fabric to service location and internal DNS resolution, etc.
@NetTecture
You make a very good point that EF 2.1 and GroupBy support.
You make a very good point on resource allocations for OData.
You make a very good point that the schedule delays:
OData in dotnet core is like permanently late.
Again, all opinions are welcome and we value constructive conversations. Thank you for participating in the conversation.
When I said your tone is aggressive and insulting, I was responding to:
Please please please read what I said again and then have someone explain it to you. You obviously misunderstand plain english.
When I used the words "not adequate", I was using the "not satisfactory or acceptable in quality" definition. I did not mean to misrepresent your words, I was responding to:
sadly OData is the stepshild of the whole stack. Damn, it is such a nice technology but it seems to fall wayside in implementation at the moment.
When I said the code of conduct is explicit, I was suggesting that individual members do not get to define the code of conduct, including myself. Microsoft has clear guidelines for code of conduct on it's open source projects. I was specifically responding to this:
And btw., I follow the code of conduct. not in the US "SJW and everyone can complain about being insulted" way, but in the good old german "stand to your facts and be right" way. Yeah, cultural difference.
agree w/ @robward-ms, as for the mention/comment:
OData in dotnet core being permanently late.
Wanted to mention that this is not necessarily negative, and actually somewhat by design, dotnet core is heavily modularized especially when compared to legacy .NET pre-core. Therefore frameworks/stacks built upon it will also likely share/follow this design feature and in architectural principle: modularization e.g. ASP.NET Core (Web API), Entity Framework Core, etc., again, are also be heavily modularized. One of the design goals from this effort/design, is to be able to rev other modules at each teams cadence, bandwidth, comfort, parallel development across modules, etc. without the dependency of rev'ing the entire .NET Core Framework in lockstep, meaning the opposite of shipping all or nothing (obviously, depending on the degree of change/rev especially in regards to core modules). This is usually the preferred approach for many runtimes/frameworks, we prefer to get latest features, faster shipments of them, etc. vs. knowing features are scoped, ready, yet held back because of coupling/dependencies on others e.g. legacy .NET. Along with the other cornerstone design reasons e.g. NET Standard, x-plat, cloud density/portability, etc., which are totally different topics and for another conversation.
So, we are in the early versions of .NET Core v2x, some of these benefits and advantages from these design decisions will not have been fully materialized, however they will, over time especially when other modules become more mature and frequency of changes/revs reduces. OData is built on top of or with:
OData literally happens via _(disclaimer: massive oversimplification)_:
With that being said, yes, especially in early phase of all things dotnet core v2+, OData is somewhat at the mercy of all of the modules is built on top of, or with _(e.g. .NET Core, ASP.NET Core, especially Web API), Entity Framework Core, etc.)_ more now, than potentially later, in early stages of v2) Again, this is what we want e.g. if Entity Framework Core rev's to vNext _and doesn't break OData_, we would want the new EF Features, etc. Yes, some could argue, one of drawback's here is there's not a monolithic release, where everything is in released in lockstep e.g. OData vNext is not ready with the latest and greatest ASP.NET Web API vNext bits are ready. However, in my experience this has rarely been the case, dev's want new features ASAP, when there ready, and they want them like yesterday.
Off-topic: _(forgive my ignorance, if list below has already mentioned or suggested):_
I think we should discuss all bugs, issues, implementation details, etc. e.g. DTO's, AutoMapper, etc. in their own thread, these issues I feel merit their own thread. Only so that we have some boundaries on this thread and that there is clear intent of what is being discussed here, which should be the shipping & status of OData for ASP.NET Core (Web API) vX.
Resource issues: would the OData Team be okay, without starting with a list of targeted features, bugs, issues for vNext's so that the community can issue PR's and help out? We can start with humble beginnings, and from this effort generate doc for what's expected, tests, setting dev time locally, etc.
I dont agree with the @NetTecture message form but the OData team have to understand that early adopters spend a lot of energy in OData and make design choices. Not having a clear roadmap and seeing the very low number of commits last weeks can make people think that they where misled into a dead end.
I agree with the fact that EF Core 2.0 is not usable in an application. We really need EF Core 2.1 group by.
Is it possible to update Analyzers too? Some referenced packages don't seem to be available in nuget anymore.
OData is a great solution and thanks for all the work you've done.
I have a very large global client that wants an OData endpoint for use with Microsoft Power BI. Weâre using .net core heavily at the moment, is .net core support usable ?
Seems to be a bit on tension on here from users etc ?
In reference to âgroup byâ is it supported, or are there work aroundâs ?
Would you expect a typical power bi userâs needs convered by .net core OData as is ?
(i do realise itâs hard to answer without a specific example)
Thanks for your time.
I think this whole discussion about group by support++ is confusing. It seems you discuss features that should not be part of / is not part of OData. Or am I wrong? My understanding is that the OData library is an abstraction over IQueryable (Ok, maybe too much of a simplification, but you get the idea)
If some of the âIQueryable implementationsâ out there in the wild (like Entity Framework) does not support group by, should this affect OData at all? Is there some obscure dependency between OData and EntLib?
@mickdelaney We're using OData with ASP.NET Core 2.0 on a huge project.
So far, the only challenge we encountered is the JSON query support, which is a problem with EF Core, and not OData.
We don't need group by support, so I can't comment on this.
Bottom line - Use it, but with caution. Make sure you understand exactly how it works, and work against a well defined set of requirements, so you can map those requirements to existing capabilities.
@mickdelaney Its been a while since I used PowerBI with OData... but my experience so far has been that it simply sucks all the data out of the source with really simple queries and then does any operations the user wants (grouping, filtering etc.) on its internal copy of the data - I don't think you need $groupby support for PowerBI to make use of your data source. Note that if you have a low default page size and a lot of data its not smart enough to request bigger pages by itself so the initial ingestion of data could take a while.
@mickdelaney Take my word with a grain of salt, but we are currently migrating a sharepoint-data-based application (for a global customer as well) to a database-based application using the nightly .net core builds. We also plan on using PowerBI in the future and I think the features needed for this are mature enough. We currently have some issues with batch queries only being able to perform 1 request, but I currently have no time to look into it if it's our fault or not - we can work around it so it's no top priority right now. The basis of our (quite complex) system is working right now and we are working on fixing some smaller issues regarding our adaption.
There are 20 issues open but for us there was no showstopper yet.
We expanded on code from @gordon-matt who now has released a library containing his GenericODataController, he might be able to tell a bit about the maturity as well.
@mickdelaney, We are using .Net Core WebApi OData in an application using EF7/Orchardcore/Syncfusion controls. All sorting/filtering/grouping commands generated by the Syncfusion Grids work very well. The only issues we have comme from EF7 2.0 that have missing features like In memory group by instead of sql grouping and a bad support for Oracle (Oracle is very late on their .Net Core driver and EF7 driver. We use Devart driver for now).
@Compufreak345 Thanks for the mention. I am glad to see that code is useful to you. Feel free to contribute back to the repo if you'd like to do so.
As for my opinion on the maturity of OData for .NET Core, I use it everywhere throughout my own framework/CMS and a few issues did come up, but they were pretty much all dealt with. I am quite happy about the state of it at the moment. However, there is a new issue I just logged recently with it being broken in .NET Core 2.1 RC (#1447). I assume this will be fixed soon after the final release of 2.1 though. Other than that, all looking good for my use cases.
Thanks so much everyone for the comments, really appreciated...
I feel alot better about going down this road now !!!
Regards
@gordon-matt I will second your statements. I've been using it since Beta-1 and it has fulfilled the majority of our simple use cases. We've only had a few minor issues that I wouldn't consider to be showstopping for a major app (combining a filter with an expand on a field that is a calculated SQL view column).
To the folks that made this possible, I give thanks. It has enabled me to keep moving down the aspnetcore path while providing our frontends with critical querying support.
@mickdelaney You should be in good hands.
@all
ASP.NET Web API OData 7.0 is available on Nuget.org now, you can download it from:
Please try it out and let us know any problems, concerns, questions. Thanks!
Regards,
-OData Team
We aren't able to use this alongside Swashbuckle with ASP.NET Core 2.1 and .NET Framework 4.6.2 due to soemthing related to these issues
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/581
https://github.com/rbeauchamp/Swashbuckle.OData/issues/154
Is there a plan to get OData working seamlessly with tools such as swashbuckle? We've had to remove our usage of OData given this issue
Wondering if there is any update on the question @fiksen99 asked related to Swashbuckle integration etc?
We started a migration project towards .net core, but a few services expose OData endpoints side to side with regular endpoints, and we need to expose these endpoints in the swagger.json that we generate (we use the generated json to deploy in Azure API management gateway).
Most helpful comment
@all
ASP.NET Web API OData 7.0 is available on Nuget.org now, you can download it from:
Please try it out and let us know any problems, concerns, questions. Thanks!
Regards,
-OData Team