I am working on setting up a multi-tenant site, where users can select a theme. Each of these themes have different settings, so I would like someone to be able to select a theme and then when they edit their site settings it would bring up a form to allow that. I am sure I could do this through hard coding data, but it would seem that I would be better off using plugins to allow new theme plugins to be added and remove the need to magic strings or having to create a dynamic settings page that reads what fields to display from a database. There is plenty of documentation on things like MEF, but I need some help on figuring out how to display a unique view for each theme and then store the results. Any help or direction would be appreciated.
C# – Plugin Strategy For MVC 5 Site
asp.net-mvc5c
Related Solutions
When tags are submitted by the author of a blog, they are under a form of a simple string (with either comma-separated values or, like on Stack Exchange, simple spaces). This is the only moment in the workflow when all tags are appearing as a single string.
The controller then splits those tags and trims them. At this stage, those tags become a Collection<string>
(or Collection<Tag>
if there is specific data or business logic associated with a tag.) Depending on your specific needs, you may need to use other generic collection classes, such as a HashSet<T>
if you need to quickly search through the sequence of tags.
The controller may then persist those tags together with the article, the title, the author info, etc. Depending on the persistence layer (i.e. the type of the database) you use, the tags may take different forms, but usually they will still be considered as some sort of array and stored one by one, not as a single value.
Finally, when it comes to displaying the tags, the controller loads them from the persistence layer (the tags are then appearing in a form of a Collection<string>
/Collection<Tag>
), and stores the collection (eventually as IEnumerable<string>
) in the model, passing the model down to the view.
The view enumerates those tags and displays the corresponding HTML.
Looking at your code, I'm not sure what are you trying to do. I guess that Tags
is a sequence in your model, but you're displaying only the first element in your view (line 54 and 55). Why?
This is also why I asked in my comments how are tags displayed in the form. Here's one way to bind an array to a sequence of check boxes; I'm not sure this is what you want or need. Probably what you actually need is something similar to Stack Exchange tagging: a single text field where a user can enter one or more words (or comma-separated values in your case). For instance:
data-center, rack, power-management, wiring
will be entered in a single text box and result in four tags: data-center, rack, power-management and wiring.
This leads to the difference between:
The view which shows a form to an author, letting him modifying the article and its tags, and:
The view which shows the article to the end users.
The first view can deal with all tags represented as a simple string. It already does when it comes to submitting a form: the value of a text box—a simple text, is translated to a string which can then be parsed like you did in your code on line 79 with a Split()
. Although disturbing,¹ you can also use a string to populate the form when the author wants to modify an article (this makes it possible to use the same model in both cases.) While the model will contain a string containing comma-separated tags, try to use Collection<Tag>
as much as possible within the controller itself. The only locations where you should see a string are the boundaries: when the controller receives the input and when it creates a model.
On the other hand, the view which shows the article—and the tags—to the end user should rely completely on IEnumerable<Tag>
representation which should be pushed by the controller through the model down to the view. It's the view which will use the sequence to enumerate through the values with a foreach
, generating the corresponding HTML.
A final note: when you'll get your code finished, compiling and working, make sure you post a few parts to CodeReview. There are a lot of things to tell about the code in its current state.
¹ The approach is disturbing because a concatenated string is a wrong data structure for tags. The right one remains a sequence (such as Collection<T>
). The problem, in your case, is that you're relying on the same model both for generating the form and getting the submitted values. Since you're forced to use a string in the second case, using a sequence in the first one will require to have two different models, which will make your code more complex than it should be.
Using strategy objects in the described way is a good start to simplify your PointBase
class, I would not hesitate to introduce them even if they do not solve your problem with the BreakEven
property.
For allowing custom properties, you could provide some kind "extension mechanism" in your PointBase
class (which I would rename to Point
after the redesign). In the most simple form, this could be just a list of custom properties for each Point
object, together with a list of their values (and the list is empty by default). This might boil down to some kind of EAV model. EAV is sometimes seen as an anti-pattern, but for this specific case its usage is fine as long as you do not use it for the majority of properties, only for your "special custom properties".
See also this former question on "Programmers" about custom fields. In my answer there, I mentioned Martin Fowler's book "Analysis Patterns" - I am pretty sure it will help you for your problem, since it contains a very extensive discussion how to model measurements and observations, including (custom) properties and similar things.
Best Answer
You do not need MEF or plugabble stuff. Using IoC container will be enough for MVC5 I have used Windsor Castle with great success and lately also Autofac.
Then you have all your controllers made by factory and you can have service for selecting layout in your controller. With this service you query database for user settings and set your model/viewbag with needed info. I did something like it for silent release where only pilot users got new look and new features aka feature switch.
Also you can switch your layout by using "_ViewStart.cshtml"
https://www.codeproject.com/articles/808894/ioc-in-asp-net-mvc-using-autofac
http://www.c-sharpcorner.com/UploadFile/dacca2/implement-ioc-using-unity-in-mvc-5/
On finishing note you can also do it with static class that has config from database but then you have to do a lot of ifs.