Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Sharing ViewComponents Between ASP.NET 5 Projects #3237

Closed
TLHamilton opened this issue Sep 30, 2015 · 23 comments
Closed

Sharing ViewComponents Between ASP.NET 5 Projects #3237

TLHamilton opened this issue Sep 30, 2015 · 23 comments

Comments

@TLHamilton
Copy link

I am attempting to model our current Web Forms Applications as ASP.NET 5 Visual Studio 2015 single Solutions/Projects - I want each application to be in a single ASP.NET 5 VS Solution/Project. As part of this effort, I believe that I need to share a number of MVC6 View Components with each of the individual projects. These will be used to construct common layouts.cshtml files and other shareable components. (1) I have looked into "Shared Projects" and I cannot seem to access their content from ASP.NET 5 projects. (2) I have looked into the project.json "content/contentFiles" properties, and I cannot get them to work. (3) ASP.NET 5 projects do not have build events that I could use to copy content files. So, basically, I am at a loss as to how to proceed with share content between ASP.NET 5 projects. Please either directory me to a better place for this question or help be move forward. Part of what I am trying to do is convert a large number of Web Form User Controls to layout.cshtml files and share them.

Thanks.

@Eilon
Copy link
Member

Eilon commented Sep 30, 2015

You can use a global.json file (all ASP.NET 5 projects/solutions have one by default) to share projects among multiple solutions. You can find more info here: http://docs.asp.net/en/latest/conceptual-overview/understanding-aspnet5-apps.html?highlight=global%20json#the-global-json-file

What you'll end up with is a file layout kind of like this:

/projects/sharedsolution/sharedproject/global.json
/projects/sharedsolution/sharedproject/project.json
/projects/solution1/global.json
/projects/solution1/project1/project.json
/projects/solution2/global.json
/projects/solution2/project2/project.json

And in the global.json files in solution1 and solution2 you'd set the projects node to point to something like "projects": [ "src", "test", "../sharedsolution" ]

This allows all the solutions to also references the projects in the shared solution (or each other, or whatever).

@TLHamilton
Copy link
Author

Thanks very much for a prompt answer. I had hoped there was an easier way of sharing that I was finding. I will test it out and submit another issues if I have any. Just great!

@TLHamilton
Copy link
Author

After reviewing your response and my code, I realized that Visual Studio 2015 was already updating the global.json file when I added a shared project to another solution and referenced it. Where I think I am having my real problem is trying to access View Components (.cshtml files) that are in the shared project from another main project. I have tried extending the IViewLocationExpander interface to point to a directory in the shared project, but it looks like only directories inside the main project can be access by the extended class. I have even tried added a full path to a View Component and the extending class could not find it. Any idea how I can access View Components from a shared project? This is what I think the mvc6 Shared Project functionality is suppose to provide, but it does not seem to work yet with ASP.NET 5 projects.

Thanks again.

@TLHamilton TLHamilton reopened this Oct 1, 2015
@danroth27 danroth27 changed the title Sharing Content Between ASP.NET 5 Projects Sharing ViewComponents Between ASP.NET 5 Projects Oct 1, 2015
@danroth27
Copy link
Member

@rynowak

There isn't a good way to do this right now. Your ViewComponent class can live in a separate project (just like Controllers can) but the views need to live in your current project.

Adding to backlog.

@TLHamilton
Copy link
Author

Thanks for your answer. I will just have to wait.

@Eilon Eilon reopened this Oct 2, 2015
@Eilon
Copy link
Member

Eilon commented Oct 2, 2015

@TLHamilton we'd like to keep this bug open so we can continue to track the scenario. Thanks!

@TLHamilton
Copy link
Author

With respect to creating sharable View Components that are self contained and encapsulate their own <script> tabs, please consider moving the _Layout.cshtml tab that contains the default scripts to above the @RenderBody() command. In this way the possible required jquery and other javascripts will already be set before the @RenderBody() command is executed causes other scripts that need them to be executed.

Thanks.

@mnguyen284
Copy link

You can keep your View Components and their views in the same assembly as resources and consume them from a website project using EmbededFileProvider. Please look into FileSystem repo for an example of EmbededFileProvider.

@TLHamilton
Copy link
Author

Fyi. I have taken the CompositeFileProvider and include two PhyiscalFileProviders in it, one for the main project and one for the shared project. In this way the main projects views are located first and the shared views are found second. Everything is now working just fine with this approach.
Thanks.

@joaquin-corchero
Copy link

Hi, so what is the suggested implemetation for this?

Thank you

@skyflyer
Copy link

@joaquin-corchero, if I understand this correctly, this bits were implemented for RC2 (not yet released). You will (eventually) be able to share view components between projects, but you will need to configure your file provider accordingly. In order to do that with the latest bits form myget, you can follow this blog post.

@skyflyer
Copy link

skyflyer commented Mar 6, 2016

@Eilon,

would you care to comment on the state of this functionality? You mentioned you'd like to keep this open to track the scenario. Is there something we can expect for RC2/RTM? I've also talked about this scenario in Nuget issue 2262.

@Eilon
Copy link
Member

Eilon commented Mar 6, 2016

@rynowak has been working on some issues relating this scenario. @rynowak ?

@rynowak
Copy link
Member

rynowak commented Mar 7, 2016

@skyflyer - this is already possible in RC1 using the embedded files provider. https://github.com/aspnet/Mvc/tree/6.0.0-rc1/test/WebSites/RazorEmbeddedViewsWebSite

RC2 makes it a little easier. https://github.com/aspnet/Mvc/tree/dev/samples/EmbeddedViewSample.Web

We have some work in the pipe to make it more first class and potentially even automatic #4089 - assuming that this is all your code and you have a build-time reference to your shared project, it's fairly straightforward.

There are lots of challenges related to redistributable 3rd party components that we won't fully solve.

@skyflyer
Copy link

skyflyer commented Mar 7, 2016

@rynowak,

thanks for the pointers. I'm aware of embedded file providers solution (I've pasted a link above a blog post outlining the steps) and I will give a look at RC2 solution tomorrow. Somehow, I was under the impression it is a temporary hack (I guess I was wrong). The #4089 looks interesting, albeit a bit over-engineered.

I'm working in an enterprise environment and am seeking a "future-proof" and MS endorsed solution to presented challenges, so that MS enterprise customers have a clear path forward, given that it is RC time already. If Microsoft.Extensions.FileProviders.Embedded is the official way to go (as an additional provider, of course), that's fine. Is it? Or are you planning on implementing 4089 for the RTM?

Just my $0.02 regarding this (and mostly 4089, but keeping this comment here, anyway) and I guess you're all aware of this already: Django's apps (and middleware) (as well as Ruby on Rails' gems) solve those issues in a very nice way. For instance, each "app" that gets registered, participates in finding the "templates" and acts as a part of the whole. Of course, there aren't just templates, but views (think controllers), tags (think view components) and other parts (template filters anyone?) that make up the ecosystem. The system is simple and works well and for different scenarios (how will the static files be solved with "embedded file provider" for instance?). This is something which could (perhaps?) be addressed with the proper structure of the nuget package and consumption of that package in a target project (either by leaving the files where they are, or by using something like Django's manage.py collectstatic).

A not too far-fetched scenario would be, for instance, providing a simple "blog app", consisting of: some models, controller, a couple of tag helpers and view components (think: latest blog posts, blog links...), a couple of razor templates and some styling assets (images, CSS file, ...). Embedded file provider solves the razor templates, while compiled assembly solves the controllers and tag helpers, which leaves static content assets in the cold (and I don't think creating two packages (NuGet & Bower) for one "add-on" is a good idea).

I hope I haven't been too broad with this discussion in this particular issue. If I have, I apologize.

@rynowak
Copy link
Member

rynowak commented Mar 7, 2016

@skyflyer - You're not being too broad, this is in line with our thinking.

@skyflyer
Copy link

skyflyer commented Mar 7, 2016

@rynowak, excellent (and exciting) news! Would you mind commenting my two questions above? (4089 wrt/ RTM and embedded providers being a way forward for the forseeable future)?

@Coolwayfarer
Copy link

@rynowak waiting to hear an answer for @skyflyer 's questions...

@rynowak
Copy link
Member

rynowak commented Apr 20, 2016

@skyflyer @Coolwayfarer - Sorry, I missed that you had asked another question!

We did #4089 for RC2 actually. There's a new application parts API that lets you add/configure assemblies that together represent your application. We've updated the controller / taghelper and view component discovery systems to use application parts, instead of some hidden other service.

The idea is that in the general case where you have a build-time reference to everything you want to include then it 'just works'. Is you want to exclude a project/assembly but still build against it that's possible now with 1-2 lines of startup code. If you want to include a project/assembly that you didn't reference at build time that's also 1-2 lines of startup code.

Regarding Razor and views, the embedded file provider strategy is what we'd recommend right now. I only say right now, because if we find a way to make it work without embedding the files in the future that might be better. Regardless the embedded file approach is a safe bet.

Now what we haven't done here, we haven't done autodiscovery of Razor views via embedded providers, and we have some work to do around making this 'just work' with the references provided to your views at compilation time. For RC2 configuring the file providers and compilation references remains manual.

/cc @javiercn - we need an announcement post for application parts.

@danroth27
Copy link
Member

we haven't done autodiscovery of Razor views via embedded providers, and we have some work to do around making this 'just work' with the references provided to your views at compilation time

#5144

@danroth27
Copy link
Member

We are also looking at precompilation of views in libraries: #3917

@danroth27
Copy link
Member

Closing since all outstanding items are tracked by other issues.

@TLHamilton
Copy link
Author

Sounds good for the future. For now I am using a combination of gulp to copy views into target project's View folder at build time and access them with PhysicalFileProvider at run time. I can send details if interested.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants