Asp.net Core 2 Domain dependent View selection? - asp.net

I have a new multi-tenant web application in ASP.NET Core 2.0, single DB.
I've established a method of determining a particular request's 'TenantId' by examining the domain in a simple piece of middleware.
I've also established a DataContext which applies TenantId filters to applicable tables as needed.
The last thing I'm unclear about is how I can differentiate Views/partial views based on the TenantId whilst sharing the controllers.
I think some scheme where the app first looks in some kind of TenantId sub-folder for the customized tenant's view and if it can't find it, it goes through the regular steps to locate the view... might work okay? Is this a reasonable approach? In other words, it should use the specialized tenant view if it exists, otherwise use the default view.
Would this involve building a custom view engine of sorts?
I've tried something similar with tenant based Html fragments, but it was a pain maintaining it, so I'm looking for something more straight forward on this project.
I'm open to other suggestions of how to implement this functionality as well.
Thanks in advance!

You don't need a whole custom viewengine, you can implement an IViewLocationExpander to make it check various locations for views.
In my project I have mutliple tenant support with both shared themes and tenant specific themes. I can override any view by dropping a copy below the theme folder, ie the main view could be Views/SiteAdmin/Index and I can override it in /pathtothemes/themefolder/SiteAdmin/Index
You can see my implementation of IViewLocationExpander here.
How you register your IViewLocationExpander is like this:
services.AddMvc()
.AddRazorOptions(options =>
{
options.ViewLocationExpanders.Add(new cloudscribe.Core.Web.Components.SiteViewLocationExpander());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
;

Related

Modular architecture to encapsulate functions in Symfony2

What I want to develop....
I am currently developing a SaaS-solution (Symfony2) to build HTML-presentations or better slide shows. Users can log into an administration UI and create presentations. This presentations can be played later. A presentation consists of elements. The elements can be images, texts, videos, pdf and more.
This element types should be encapsulated from the user interface. So extern developers can develop such new modules (element types) with defined interfaces and inject it into the system.
If a new module is finished, we move it to a specific directory in the symfony2 directory and the system detect the new module. No hardcoded-changes in the administration ui system should be neccessary.
Each module has a own "product-number". So we can use a database to enable or disable modules for different users.
What functions must be implemented by a module?
In the administration ui the user has the possibility to create a presentation and add elements of different types (the modules). User sees a timeline with the elements. When he clicks on an element, the editor for this element will be shown under the timeline (Parent-Child-View). Each module has different editors. A text-module needs other configuration-possbilities than an image-module.
So, in admin UI we need functions to edit elements:
createNewElement() creates new entry in the database (module has own tables, e.g. mod_text_elements)
renderEditorView() generates HTML which will be shown in the administration ui with module-specific inputs. E.g. image-upload/crop, WYSIWYG-editor, ...
saveEditorInputs() the module needs to handle the data entered in the editor and save it to the elements entry in the database
deleteElement() to delete an element
The output for the presentation:
Later we want to play this presentation. So a loop goes through the presentation elements and asks the modules of the element what and how to show it.
renderPresentation() to render (HTML) an element for the presentation
Database
I've made a little er-diagram of a possible solution to save the information about modules and elements in a database. The yellow entities are module-specific tables.
How to realize this in Symfony2?
My frist idea is to define an interface which have to be implemented by the modules. But which class has to implement this? Controllers?
Are modules = bundles?
How to realize the View-in-View of the editor? The editor of the module (e.g. renderEditorView()) should be viewed in the user interface of the administration ui.
I'd do it by hooking in to the EventDispatcher Component.
Your 'Master' Controller would define a set of events which correspond to the standard CRUD actions you've defined above ... onCreateNewElement(), onRenderEditorView(), etc. You'll probably find a dozen more to provide hooks for as you build your application (allowing plugins to add tools to a toolbar for example).
You'd define a Service (this doesn't HAVE to be a Controller Class), which looks for new 'modules' and adds their correctly-named methods as listeners for your custom application events.
Are modules = bundles? Well, that's entirely up to you. Are you going to provide a method for users to 'install' new modules specifically for your application? Then what a module needs to look like is entirely up to you. Are you going to slip Composer into the mix and allow modules to be installed that way? Places a couple of constraints on the structure, but still pretty much up to you.
How to realise the View-in-View? Again, that comes down to exactly how you define the interface for your 'Event Plugins' and what kind of access they have to resources like TWIG and YAML config.
The question you're REALLY asking is How do I add functionality to an application without hacking existing code ... and the answer is EventDispatcher. The rest is up to you.
There is another way to expand codebase with custom "modules": Dependency Injection Tags.
It works like this:
You create core of the app, which implements basic functionality and registers compiler pass which handles code extension
Modules can be part of the core app OR moved to external bundles
Each module must be registered in DI container with tag supported by your core app, so can be handled properly (adding menu positions, new element types as in your example)
Symfony DI compiles all services and stuff so all modules are available within app instantly (so you can for example iterate over collection of prepared items without need to dynamically building it)
In my opinion EventDispatcher is better for handling real-time actions, like sending notifications when new entity is created (e.g. controller/service dispatches event, some bundle subscribes it and send notification).
When you want to extend core I would recommend DI tags. Of course you have to build all the core (interfaces and whole architecture) so modules can extend existing services' data, then you only use your services.
Whole Symfony full-stack framework is based od this tags, so there is a lot of existing code to investigate for getting the concept.
Please let me know if it's clear enough what I wrote and what's in Symfony docs. If you need some additional info, I'll try to help.

Symfony2 inject an array of services into a controller from config.yml

How I can inject an array of services from config.yml giving class names (with namespaces) to a controller? I need to run a function from each of this services in the controller. At the moment I use $this->get('service'); in the controller, but I need to make controller independent from services. Is there a way to do this?
Edit
I don't know names and how many services will be injected, though all of them implement an Interface.
Edit2
Well, probably I did not express correctly my thoughts. I have a bundle named Widgets. It has an array of widget names, display widget holders for each widget and with AJAX I get the content and display it. At the moment I have in the Widget controller hardcoded some widget deffinitions (title and id for Ajax) and some are retrieved by calling getWidgetList from some controllers from another bundle. Well I need that the list of the widgets wont be hardcoded itself in the widget bundle. I need a way to pass this list from the config.yml. Any ideas?
Injecting an array of services is, generally speaking, not the right approach (even if there was a way to do it, which I don't think there is)
The whole reason you don't want to write container-dependent code is to keep your codebase flexible, lithe, and testable. A variable array of services is, in practice, just a mini container, so if you implemented that you'd just be shrinking the scope of the problem, not eliminating it. You'd still be making your code dependent on an arbitrary bucket of services.
I strongly recommend explicitly defining each service your controllers need (as outlined by the links in the comments from Rufinus and Cerad) or look into using something like the jms/di-extra-bundle.
Update
Maybe you need to do more research on the configuration options available?
How to Create Friendly Configuration for a Bundle
The Config Component
http://symfony.com/doc/current/cookbook/bundles/configuration.html

Sending a model for use throughout all views linked from a layout

I am working on a web service built on ASP.NET MVC 4 and have run into some trouble figuring out how to manage a model after log in so that it is widely available to all action functions created in the back end.
For example) Let's say I have built a service that allows a user to log in and manage multiple databases. After he logs in he is redirected to a view that allows him to pick which database he would like to manage, which inherits the old layout. After he clicks on the database he wants to manage, the model of this database is passed to the index view of a manage controller which utilizes a different layout than before. All of the managing action links are coded in the layout but the model was passed to the index page. He needs the model to be available for all the ActionResults in the managing controller, but a model can't be passed to a layout, so this is where I'm stuck.
Does anyone know of any good references or guides on how I can utilize a model throughout a whole layout? Or something a long these lines? I'm not sure the technique I used for this problem was the best but I don't know how else to go about this. If anyone knows a better technique of going about this please let me know.
Thank you!

"Subclass" MVC Extension

I'm coming from a ASP.NET Webforms application. I'm using a third party control from which I created a descendant to set some default values. I then registered that class as a tag and I'm ready to go without setting the options ever and ever again.
Now I want to go to a MVC based application. I'm curious how to do that. Is there a way to "subclass" an extension there, too?
Edit: Done this with DevExpress MVC Grid extension
The third party control is another story entirely, and the vendor would have to release an ASP.NET MVC version.
However, in simple terms of creating re-usable code in ASP.NET MVC one option you have is to create custom HTML helpers. It basically ends up being a method that you call which outputs markup, which can be made fairly powerful fairly quickly.
There are a lot of resources on various HTML Helpers, and keep in mind that the "documentation" you find on Google has changed significantly over the versions of ASP.NET MVC, so take care to ensure you're not limiting yourself to "an old way" of doing things. There are also a number of commercial as well as free products and open-source projects with handy helpers and extensions.
The third party control uses a Settings class. I have created a new settings class, which sets the default values in it's constructor.
Then I have written an extension method that reads like this:
public static GridViewExtension GridView ( this HtmlHelper html, Action<CustomGridViewSettings> settings ) {
var mySettings = new CustomGridViewSettings();
settings( mySettings );
return html.DevExpress().GridView( (GridViewSettings)mySettings );
}
Usage is then analog to the samples online #DevExpress page and I omitted the sample class here.

Component controller in Spring-MVC

I am designing a web application that requires loading multiple components on a single page. (In terms of page layout is similar to Google reader) I like to keep these components separate from each other (for reasons such as reusability). For example, I have a left panel that let's user navigate among multiple feeds that he's subscribed to (user specific) and on the right side of that we show the contents of that feed, and maybe a right panel which shows some specific info about that specific feed.
My understanding of MVC and more specifically Spring-MVC is that each controller is in charge of the entire page. Here are 2 solutions that I have came up with after researching this a bit, and none of them sounds good to me.
Have a main controller that is mapped to that URL, and then load the other components from inside the jsp file. This is doable but doesn't sound like a good solution.
Using portlets.
I want to know what are the best practices. This sounds like a very common web design issue in MVC frameworks, how do people do it?
Spring MVC controller is usually "in charge" :-) of handling a particular request which does not necessarily mean that said request results in a monolithic page being presented to user.
Since you're talking about Google Reader-like functionality, perhaps you'll be using AJAX to load / navigate between different components on your page? If that's the case, you can easily map your 3 components to separate controllers (via separate URIs) plus have one "main" controller to initially load the entire page.
If that's not the case and your page is static, you can have your controller act as "router" of sorts by first instantiating your components and then directing commands / requests to an appropriate component as necessary. Each component would update its own part of the model after which your "main" controller would return the view to be rendered.
Can you use portlets for this? Sure. But if we're talking about a single page it might be a tad overkill.

Resources