Closed MichaelPeter closed 3 years ago
Not sure if I made the changes in the way you would have wanted them to be made. Feedback highly appriciated.
Question here is if IAsyncCollection makes sense. It would only be advantagous for scenarios with big folders (5.000+ Items) where the http messages is streamed back to the client. And the client starts displaying the contents of a folder while they arrive in the http stream.
Against it speaks if maybe IAsyncCollection maybe has some performance pentality. The unterlying implementation does not yet take advantage of the IAsync enumerable.
Thanks for your input and contribution. I am a bit busy at this moment, but I'll try to review your changes this week. I would like to keep compatibility with the traditional .NET Framework for now, unless there are important reasons (this project is often used in .NET Framework v4.x projects). Using IAsyncEnumerable
would only be useful when you need to access external resources that return information in chunks. In most situations, it won't have any benefits and it's not trivial to support it in classic .NET Framework.
Hello thanks for your feedback.
When you review the changes there are Precompiler conditions the IAsyncEnumerable usage in the code is limited for Net Standard 2.1 and Net5.0 and up. All previous versions Net 4.X or NetStandard 2.0 or lower which do not support IAsyncEnumerable yet, still have an interface Task<IEnumerable
What breaking change I introduced for .NET 4.X
, GetItemsAsync
returns now Task<IEnumerable<IStoreItem>>
instead of Task<IList<IStoreItem>>
since the advantages of IList (Like Count) have not been used. This way the resultset COULD also be streamed. But this breaking change means you just have to change a return type.
NetCore/Net 5 will have the breaking change of now returning IAsyncEnumerable.
The question is if any webdav client takes advantage of streaming folder content. Since WebDav does not support anything like paging.
The suggestion for removal of support for Net Standard 1.6 was because only NetCore 1.0 requires it. And the only scenario I know where Net Standard 2.0 is required is UWP Apps on Xamarin. And you wouldn't host a WebDav Server in UWP. And I think most developers switched from NetCore 2.0 to NetCore 2.1 on the server side.
Here Net Standard support: https://docs.microsoft.com/en-us/dotnet/standard/net-standard
Also a small hint regarding the switch from XDocument.Load(request.Stream) to XDocument.LoadAsync(request.Stream).
Starting from Aspnetcore 3.1 Syncronous Stream reads are by default disabled (AllowSynchronousIO https://github.com/dotnet/aspnetcore/issues/7644) So with default settings XDocument.Load will throw a Exception if AllowSynchronousIO is not explitictily set. But AllowSynchronousIO is only a compatibility switch.
Now XDocument.LoadAsync is only available since Net Standard 2.1, so previous versions cannot use it.
I can't yet switch to .Net Core 5 so I appreciate the continued compatibility.
I reviewed your changes and I have several comments:
<ApplicationIcon/>
, <StartupObject/>
, ... which are pretty pointless.async foreach
would only be benificial when you have a lot of items that need to be fetched asynchronously on a high-concurrent server. To maintain backwards compatibility with older versions, you need a lot of additional code that is hard to maintain.I do think there is a lot to improve on NWebDav, but just aiming to use the latest .NET 5 features is not my goal. I would rather improve the logging framework (just inject ILogger
) and the ability to use the standard .NET DI container. But I don't want to make much breaking changes. NWebDav is used in several projects and not everybody can switch to the latest and greatest .NET version. I want to maintain compatibility with older frameworks as longs as they are still relevant.
Hello @ramondeklein,
I removed ApplicationIcon and StartupObject, I did not add them intentionally, seems to have been a some visual studio functionality has been fixed.
I must admit I was not sure what is still the purpose of the kestrel sample since it was conceived in the infancy of netcore. To me it seemed like a sample for what is now aspnetcore. And samples are mostly for new applications, which tend to be on newer frameworks.
I agree .Net Standard 2.1 would be sufficient. I added a .NET5 since Microsoft announced that .NET5 should replace .NET Standard. But for now it could be removed since it bears no advantage..
See here: https://visualstudiomagazine.com/articles/2020/09/16/net-standard-future.aspx https://devblogs.microsoft.com/dotnet/the-future-of-net-standard/
Think it is also a bit of a philosophical question. Do you go for the new an shiny or the old established that actually makes money. Think you need both, backwards compatibility and the new and shiny, depending what you want. And you shouldn't just do what Microsoft tells you to do.
But we arrived in a new nodejs and javascript world, where Long Term Support .NET Versions means 3 Years support from Microsoft and where NetCore 1.X is obsolete like .NET Framework 1.0 when .NET Framework 2.0. became the Minimum supported Framework Version.
.NET Framework is getting retried / will very slowly die. We can like it or not, but it is a fact. Is NWebDav a framework that preserves or that moves forward? So far it can still be both.
But yea Net Standard 2.1 would be sufficent for now.
For me either way is ok. But would you stay with Task
Here I agree with the ILogger topic but for me it was importaint to get NWebDav running without having to activate the compatibilty switches in NET5 (AllowSynchronousIO)
I agree with your second point that Kestrel based applications will typically be .NET Core and I don't think a lot of people are still targetting pre .NET Core 3, so no problem there.
Although .NET Standard 1.6 isn't used a lot, there is no need to upgrade to .NET Standard 2.0, because I don't think we need any features of .NET Standard 2.0. Switching to .NET Standard 2.1 is only suitable when you have lots of items in your collections and you are able to asynchronously provide them using IAsyncEnumerable
, which is an edge-case for now (might change in the future when IAsyncEnumerable is more widely adopted).
Supporting older frameworks is not a philosophic question to me, but there are a lot of legacy applications that are written in .NET Framework and won't be ported to .NET Core soon (or maybe never). I am working for two companies that both have a large .NET Framework codebase that won't be ported. One of them also uses NWebDav (that's why I created it in the first place). Some code is even running .NET Framework v4.6, because it runs on old systems and isn't even capable of running .NET Standard 2.0. We are slowly migrating to .NET Framework v4.8, but even this is a precarious process when you have to deal with clients that run older Windows versions. That's why compatibility is a huge deal to me.
If the IAsyncEnumerable
implementation would only be visible within a single implementation, then an #if
would have been fine, but if you have different interfaces on different platforms, then it becomes messy and requires a lot of code changes. It feels like it is used, because we can. Not because we need to. Hope this clarifies my objections to the IAsyncEnumerable
implementation.
Supporting ILogger
and being able to plug in to the current .NET Core DI framework implementation is a change that is on my agenda for months, but I am currently working 50hrs+ on paid projects, so this project doesn't get the required attention at this time :-( I also don't want to break .NET Framework v4.5+ compatibility there, so it should be possible to use NWebDav without the .NET Core DI container and inject the classes manually (which should be the goal for each DI app anyway).
I do think we should get rid of AllowSynchronousIO
in .NET 5. What's the required change to do that?
As written with this push Request the need for AllowSycronousIO
has been solved, the Problem is starting with AspNetCore 3.1 you you cannot make sync stream reads anymore.
The problem was that XDocument.Load
reads the stream sync. The new XDocument.LoadAsync
fixes that but XDocument.LoadAsync
is only available starting from Net Standard 2.1 and Net 5.
So regarding the Framework: Target Frameworks would then be Net452?, Net Standard 1.6 (as you wrote no difference to Net Standard 2.0), Net Standard 2.1 (And maybe net5.0, even thought I also don't know an advantage yet.)
Regarding IAsyncEnumerable
I agree. Maybe there could be an extension Interface, which allows an alternative implemenation, which is called if it is there. I also wanted to test if there are performance pentalities for IAsyncEnumerable.
And no I don't want to break compatibility with Net Framework. But NetCore and Net5+ has differenet demands than Net Framework. And .Net Framework could stay compatible but for newer .NetCore and NET5+ the new capabilities could be supported.
And yes the Code gets with preprocessor commands more messy, but if you want to keep the same codebase for both, I think in future there is no other way (already XDocument.Load and XDocument.LoadAsync demand that)
There are also capabilities which could even be advantagous for Net Framework 4.X, like nullable types, which does not break compatibilitiy.
My demand is I need this library for my work on a new .NET5, maybe soon even .NET6 Project So as you need it for Net 4.8, I need it for Net5 ;)
I switched back from IAsyncEnumerable
to Task<IEnumerable>
since there is no advantage in IAsyncEnumerable right now. Maybe later another interface could be defined that supports this.
Btw: I also checked out the Performance of IAsyncEnumerable and it is actually extremly fast: In 1 Millisecond it can iterate 10000 times, in 1 second 10 million times on a single core: https://github.com/MichaelPeter/TestAsyncEnumerablePerformance/blob/master/TestAsyncEnumerablePerformance/Program.cs
Also I removed the target .Net5 and left just NetStandard 2.1, since Net5 has no advantage yet.
Also bumped the version from 1.34 to 2.01, since there are major changes, including the switch to IEnumerable
@MichaelPeter I have made some additions to your fork. Can you grant me access so I can push them to your repo?
Don't bother... I was using the wrong account :-)
@MichaelPeter Just some remarks on my changes:
CancellationToken.None
in that case).Hello @ramondeklein,
regarding your points - works for me!
So next step would be a new release with a updated nuget package?
Greetings Michael
TODO: Commits need to be squashed. TODO2: Remove support for netstandard 1.6? TODO3: Add Support for additional Method TODO4: Kick the butt of IT-Hit for charging so high prices for WebDav.
ramondklein: Contact me if you are still interested in the project. Have some ideas, also regarding Sharepoint specifics michaelpeteronline@googlemail.com