I am using ASP.NET MVC and have to develop and deploy multiple websites based on a first website.
There are variation in some controllers, some views, some scripts and some models, and the Database are different on each website (mainly columns are differents but table names remains the same).
Is there a way to handle such a thing in a single Visual Studio Project, in order to make maintaining easier, and be able to add common feature easily on every website ?
Currently, I copy the pilote project into a new VS project, and change all the variation. But I find it's not an ideal situation (because of maintaining/improving).
I have implemented something like that years ago and can give some general advice you might find useful.
First of all developing app with such "multitenancy" has nothing to do with MVC pattern itself. You can do that without MVC :D. Second, if the websites supposed to work with different business domains I am afraid there is no generic way to do what you want. In my case it was just a number of e-commerce platforms.
Anyway, consider next things.
1.Think about using sub-domain approach if you can. It will free you from stupid routing and cookies shenanigans. Basically you can map *.yourdomain.com to one app and handle the necessary logic related to tenant easily. So in my case it was an application that behaved differently depending on provided url, not route, but sub-domain, 'superclient.yourdomain.com' for example. Its not always possible or good idea, but think about it.
2.Dependency Injection everywhere. Well, its useful in general but in your case is absolute must have - try abstract any tenant specific logic in separate types and init them in one place. Its everything related to localization, timezone settings, app theme, branding info on the app header etc. Just initialize and inject where its needed. If you have something like
if (website1) {
showBlockOne();
} else if (website2) {
showBlockTwo();
} else if (website3) {
showBlockThree();
}
then you doing something wrong, its a road to insanity. It should be something like
_currentTenantViewContext.ShowBlock();
So its polymorphism over conditional operators in most cases.
3.In my case the requirement was to create an app which can work with any language so I had to handle that issue on database side as well. The problem is that if usually you have lets say for example ProductType table in database with Id and Name, in multitenant application its not that simple. My solution was to create two tables - ProductType with Id and Code fields and ProductTypeLocalization table with Id, ProductTypeId, LanguageId, Value fields to handle this problem. Requirement also was to make this values editable from admin panel...
I don't know is it the case for you, but if yes think about it before the shit hits the fan in future.
4.For situations where you need some specific fields in some database table only for one site its not a good idea to spawn them freely (in general). Consider using some generic format for that, like JSON or XML. If you have few additional text fields for specific website in some table just create one field (call it ExtraSettings or something) and store this strings as JSON in that one field. Of course you have to handle this data in separate way, but its about dependency injection again.
Also you can use NoSQL for that.
5.Provide feature toggling, different websites requires different blocks to be displayed, rules applied etc. You have to have some way to on/off them for particular website(tenant) without recompile/redeploy.
Hope it helps.
Related
I am creating a new application right now and I want to make all right at the start so I can grow with it in the future.
I have looked on several guides descibing how to make a multilanguage supported application, but I can't figure out witch one to use.
Some tutorials are old and I don't know if they are out of date.
http://www.codeproject.com/Articles/352583/Localization-in-ASP-NET-MVC-with-Griffin-MvcContri
http://geekswithblogs.net/shaunxu/archive/2012/09/04/localization-in-asp.net-mvc-ndash-upgraded.aspx
http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx
http://www.chambaud.com/2013/02/27/localization-in-asp-net-mvc-4/
https://github.com/turquoiseowl/i18n
I found that they are 2 ways of storing the language data, either in db or in resource files.
What are the pro/cons?
Is there another way that is prefered?
This is what I want:
Easy to maintain (Add/Change/Remove)
Full language support. (views, currency, time/date, jquery, annotations and so on..)
Enable to change language.
Auto detect language.
Future safe.
What is the prefered way of doing this? got any good tutorial that is best practice for 2013?
I've written a blog post convering the following aspect of a multilingual asp.net mvc app:
Database: I split table in two parts, one containing non-translatable fields the other containing the fields that need translation.
Url Routes: I normally keep the culture in the URL that way you get a well indexed ML site.
routes.MapRoute(
name: "ML",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { lang = "en-CA", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
From a base controller class you can make that {lang} parameters available to your Controller. See the blog post for all details.
Querying your data: You would simply pass the Culture to your repository or database context. The idea is to create a view model that merge the two table that you separated for translation.
public ActionResult Index(string id)
{
var vm = pages.Get(id, Language); // Language is the {lang} from the route
return View(vm);
}
Your Views: Use the .NET Resources file with the generic two-letter language code, ex: HomePage.en.resx, HomePage.fr.resx. The locale en**-US**, en**-CA** is useful for formatting currency, dates, numbers etc. Your Resources file will mostly likely be the same for English US, Canada, etc.
Images: Use a format like imagename-en.png, imagename-fr.png. From your Views make the {lang} route parameter available via an extension method and display your images like this:
<img src="/content/logos/imagename-#this.CurrentLanguage()" />
You may also have a complete separate folder for your language supported. Example: /content/en/imagename.png, /content/fr/imagename.png.
JavaScript:: I usually create a folder name LanguagePacks and JS files called Lang-en.js, Lang-fr.js. The idea is to create "static" class that you can use all over your other JS files:
// lang-en.js
var Lang = {
globalDateFormat = 'mm-dd-yy';
greeting: 'Hello'
};
On your Views, you load the correct Language file
<script type="text/javascript" src="/content/js/languagepacks/lang-#(this.CurrentLanguage()).js"></script>
From a JavaScript module
// UI Module
var UI = function() {
function notify() {
alert(Lang.greeting);
}
return {
notify: notify
}
};
There's no one way to do a multilingual web app. Use the Resources to translate your text, they can be quickly swap at run-time. You have multiple editor that can open those that you can pass to translator etc.
You can check the blog post and get a detailed example on how I do this.
I have an approach for myself based on db, however it may not be suitable for large scale apps.
I create a Translation table/entity for holding titles and texts which should be multilingual.
So, whenever I want to render a view, first I retrieve the appropriate translation from db and then pass it to the view as model:
var t = dbCtx.Translations.Find(langID);
// ...
return View(t);
And in view, I render the content like the following:
<tr>
<td>#Html.DisplayFor(m => m.WelcomeMessage)</td>
<td>#Url.Action(Model.EnterSite, "Index", "Home")</td>
</tr>
And about getting the appropriate answer, well you have several ways. You can use session:
Session["Lang"] = "en";
// ...
var lang = (string)Session["Lang"] ?? "en";
Or by passing it through query string, or combination of them.
For auto detecting language, you should decide of the following:
a) Detecting from the browser
b) Detecting from user IP and guessing geo location of him/her and setting the appropriate language for him/her
I kinda have a feeling that this question does not have a straight forward answer. For formatting and what not you should always be using the Culture and the UICulture i.e. stuff like 'en-GB' for British English and 'en-US' for US English (and yes, there is a difference). All of .Net is built around it and that way you can use local formatting without really thinking about it.
You should also check out the System.Globalization namespace for more details:
http://msdn.microsoft.com/en-us/library/system.globalization%28v=vs.110%29.aspx
As for were the culture should come from, then at least in our company the policy has always without exception from the query string. The reason for that is that if you use IP localization for example, then if a Spanish user is looking at a Spanish site in Japan and then would be switched to the Japanese version, then not exactly wrong but can be annoying if you've told the client that it's a direct Spanish link or something. That said if the culture is undefined in the query string, then using the IP to get guess with language the user would like to have, would not be a bad idea, but really depends on your clients needs.
As for were to get the translations, then it really depends, both resource and DB have their ups and downs. So the major up-points for DB are that, its easy to share between applications and if you need to update a phrase for any reason, then you can update them all through one DB entry, but this can be a fault as well, because some phrases have dual meanings and can be translated completely differently in other languages although the same sentence is used in English. The other big problem with DB is that to a degree (but this depends on implementation) you loose intelligence in VS for the phrases.
Resources of course have proper intelligence, but they are fairly static to that web application you are using, you can't share resources across applications... well not exactly true, but more or less you can't. Though that static nature is also a plus, because all of the resources are contained within the application and you know that no outside effect can influence it.
In reality it really depends on the project in hand. you simply have to way your own pros and cons and decide for your self... sorry. But if it helps at all, I can tell you how things are in my company. We make several applications, that share the same phrases all across various web applications. We used to have it in DBs, but what happened was that the translations kept going array, meaning a client asked for a better translation in Spanish for one app, but that made no sense what so ever on others. That happened more than you might think. Then we moved to the resources, but what happened there was that when one app's translation was updated, then no-one remembered to update the other apps and it actually happened that 3 different apps translated the same term in 3 different ways. In the end we decided to go back to the DB, because the ability to change all of the translations at once meant more to us, then the fact no outside influence could effect it.
In general there are other pros and cons as well, but all that is fairly irrelevant compared to the above. You really need to ask how you are using the translations. As for general editing (excluding the above point), then aider approach works just as well, you can just as easily change and edit or extend translations with both approaches.
That said, if the DB and the DB calls are designed badly, then adding new languages can be easier with resources, simply copy the resource file, add the culture extension to the name and add the translations to the resource and you are done, but again, completely down to the DB design, so that is something to keep in mind when designing the DB and says fairly nothing about holding the translations in the DB.
By in large I would say that the resources are easier to use and very easy to maintain and extend (and they are already built into .NET) though DB has a clear advantage if you need to share translations. So if I would have to say I would say the recommended way is to use Resources, but DB does have it's place and it really depends on the project.
I've been looking at the same sources as you for the same needs but as you say it is very hard to find one preferred solution.
But I decided to go with the solution by Michael Chambaud that you have linked in your question. Reasons for this was that it was easy to implement, gave me the url's I wanted and since I'm still not 100% certain... easy to replace in the future.
In additon to this I will use jquery globalize for client side formatting.
It would be really interesting to hear what solution you decided on?
I am building a site which will need to change slightly in certain markets. For example, in a UK market, the signup form needs to perform address validation (already have this working), and on a Belgium site, we need to verify a person with a web service (already have this working). Otherwise, signup functionality is basically the same. We have these two sites working independently, but we'd like to merge them into a single codebase which can support either option based on config.
My initial thought was to use a configuration value to say "This is a UK site" or "This is a Belgium site" and display the pages based on this setting.
Ideas:
Dependency injection to load controls dynamically based on config
Factory pattern to use Reflection/Activator and load dynamically based on config
Config transforms to load different user controls by setting a tagname/tagprefix
Other?
Does anyone have any first thoughts on recommendations on where I can find inspiration for this type of design?
I would recommend to keep it as simple and minimal as possible.
Simply create something like IPersonValidator which has a .Validate(PersonDetails) method and returns an array of errors.
Edit:
On the config side, you could create a custom config section of the following structure:
<DomainSpecificSettings>
<Key name="validator">
<Value domain="www.yoursite.co.uk" value="firstValidator" />
<Value domain="www.yoursite.de" value="secondsValidator" />
</Key>
</DomainSpecificSettings>
One more thing - you don't need to use Activator. You could have a singleton Validators store which holds a single instance for each validator type and knows how to find the correct Validator according to the database config setting of the currently viewd market:
ValidatorsStore.GetValidator(string configValue).Validate(PersonDetails).
The design in this case may easily become a overkill for such a simple task. My approach is to first make it work good enough, and only then check if you need to make it more robust. Most chances are that you won't.
First, as you mention “loading user controls”, think it will be better to separate the presentational part of the implementation from the logic/validation itself. You could create(or refine) a generic user control that works for all the countries but calls logic that does the address validation in case of the UK or nothing in case of BE. Single responsibility principle or separation of concerns in the MVC world.
Also use same principles separate the different components of the page in different user controls with their logic. Every component with have their own validation before calling the final signup/register. This way you can notify the player of a validation error in the input data without having to require the full player information to do the signup. Once the full information for the player is provided and validated you can call the signup that just saves the player in the database.
About the StrategyProvider class to decide which logic to call, agree with Uri, we are going to have many places where the logic varies a between countries. But it is not something we could setup with IoC container? Don’t know much about IoC containers but if logic is “static” (when you are in website it does not change depending on request) could be possible to setup it at application start time.
Another possibility is to use the SOA pattern and call different services depending on the website you are in. (same servuces end points could be setup in config). Services for the different countries can have different logic but return a class that follows a common interface (use Adapter pattern).
I'm not sure if this is the right place for my question, but i will give it a try.
We are starting the development of a new product wich will use asp.net mvc 3 razor as the presentation layer. The application has about 7-8 different roles and all the roles have different views on wich the data will be displayed.
I've build a nice framework with the help of NHibernate and the implementation of a couple design patterns, so this side of the applicatie will be easy to adjust and apply maintenance to.
I want the presentation layer to be as adaptive as my framework and that's why i'm trying to figure out a way to have as less views as possible for all the different kind of roles but with full functionality. What kind of implementation do you use for distributing views to the end-user based on his role?
I thought about using jquery templates, but with the current possibility of views and the razor syntax it sound a bit unnecessary and not the preffered way to go.
Any information that i should keep in mind while developing this application will be nice, think about, common mistakes, best practises and suggestions etc.
Looking forward to your replies.
One way to reduce the number of views would be to use IsInRole() (or an equivalent if you have something custom) in combination with partial views. In the most simple case, you could have one view that also renders partial views within it based on specific roles. Something along the lines of:
#if (HttpContext.Current.User.IsInRole("admin")) {
#Html.Partial("_StuffForAdmins")
}
Depending of your situation, some partial views could then be shared across multiple different roles, reducing duplicate code. User interface elements that are publicly accessible by all roles could just be placed on the view itself without role checking.
EDIT: An alternative syntax is:
<div>
#if (Context.User.IsInRole("admin"))
{
#Html.Partial("_StuffForAdmins")
}
</div>
I know there are actually a number of questions similar to this one, but I could not find one that exactly answers my question.
I am building a web application that will
obviously display data to the users :)
have a public API for authenticated users to use
later be ported to mobile devices
So, I am stuck on the design. I am going to use asp.net MVC for the website, however I am not sure how to structure my architecture after that.
Should I:
make the website RESTful and act as the API
in my initial review, the GET returns the full view rather than just the data, which to me seems like it kills the idea of the public API
also, should I really be performing business logic in my controller? To be able to scale, wouldn't it be better to have a separate business logic layer that is on another server, or would I just consider pushing my MVC site to another server and it will solve the same problem? I am trying to create a SOLID design, so it also seems better to abstract this to a separate service (which I could just call another class, but then I get back to the problem of scalability...)
make the website not be RESTful and create a RESTful WCF service that the website will use
make both the website and a WCF service that are restful, however this seems redundant
I am fairly new to REST, so the problem could possibly be a misunderstanding on my part. Hopefully, I am explaining this well, but if not, please let me know if you need anything clarified.
I would make a separate business logic layer and a (restful) WCF layer on top of that. This decouples your BLL from your client. You could even have different clients use the same API (not saying you should, or will, but it gives you the flexibility). Ideally your service layer should not return your domain entities, but Data Transfer Objects (which you could map with Automapper), though it depends on the scope and specs of your project.
Putting it on another server makes it a different tier, tier <> layer.
Plain and simple.... it would be easiest from a complexity standpoint to separate the website and your API. It's a bit cleaner IMO too.
However, here are some tips that you can do to make the process of handling both together a bit easier if you decide on going that route. (I'm currently doing this with a personal project I'm working on)
Keep your controller logic pretty bare. Judging on the fact that you want to make it SOLID you're probably already doing this.
Separate the model that is returned to the view from the actual model. I like to create models specific to views and have a way of transforming the model into this view specific model.
Make sure you version everything. You will probably want to allow and support old API requests coming in for quite some time.... especially on the phone.
Actually use REST to it's fullest and not just another name for HTTP. Most implementations miss the fact that in any type of response the state should be transferred with it (missing the ST). Allow self-discovery of actions both on the page and in the API responses. For instance, if you allow paging in a resource always specify in the api or the webpage. There's an entire wikipedia page on this. This immensely aids with the decoupling allowing you to sometimes automagically update clients with the latest version.
Now you're controller action will probably looking something like this pseudo-code
MyAction(param) {
// Do something with param
model = foo.baz(param)
// return result
if(isAPIRequest) {
return WhateverResult(model)
}
return View(model.AsViewSpecificModel())
}
One thing I've been toying with myself is making my own type of ActionResult that handles the return logic, so that it is not duplicated throughout the project.
I would use the REST service for your website, as it won't add any significant overhead (assuming they're on the same server) and will greatly simplify your codebase. Instead of having 2 APIs: one private (as a DLL reference) and one public, you can "eat your own dogfood". The only caution you'll need to exercise is making sure you don't bend the public API to suit your own needs, but instead having a separate private API if needed.
You can use RestSharp or EasyHttp for the REST calls inside the MVC site.
ServiceStack will probably make the API task easier, you can use your existing domain objects, and simply write a set of services that get/update/delete/create the objects without needing to write 2 actions for everything in MVC.
Here's the story so far:
I'm doing a C# winforms application to facilitate specifying equipment for hire quotations.
In it, I have a List<T> of ~1500 stock items.
These items have a property called AutospecQty that has a get accessor that needs to execute some code that is specific to each item. This code will refer to various other items in the list.
So, for example, one item (let's call it Item0001) has this get accessor that may need to execute some code that may look something like this:
[some code to get the following items from the list here]
if(Item0002.Value + Item0003.Value > Item0004.Value)
{ return Item0002.Value }
else
{ return Item0004.Value }
Which is all well and good, but these bits of code are likely to change on a weekly basis, so I'm trying to avoid redeploying that often. Also, each item could (will) have wildly different code. Some will be querying the list, some will be doing some long-ass math functions, some will be simple addition as above...some will depend on variables not contained in the list.
What I'd like to do is to store the code for each item in a table in my database, then when the app starts just pull the relevant code out and bung it in a list, ready to be executed when the time comes.
Most of the examples I've seen on the internot regarding executing a string as code seem quite long-winded, convoluted, and/or not particularly novice-coder friendly (I'm a complete amateur), and don't seem to take into account being passed variables.
So the questions are:
Is there an easier/simpler way of achieving what I'm trying to do?
If 1=false (I'm guessing that's the case), is it worth the effort of all the potential problems of this approach, or would my time be better spent writing an automatic update feature into the application and just keeping it all inside the main app (so the user would just have to let the app update itself once a week)?
Another (probably bad) idea I had was shifting all the autospec code out to a separate DLL, and either just redeploying that when necessary, or is it even possible to reference a single DLL on a shared network drive?
I guess this is some pretty dangerous territory whichever way I go. Can someone tell me if I'm opening a can of worms best left well and truly shut?
Is there a better way of going about this whole thing? I have a habit of overcomplicating things that I'm trying to kick :P
Just as additional info, the autospec code will not be user-input. It'll be me updating it every week (no-one else has access to it), so hopefully that will mitigate some security concerns at least.
Apologies if I've explained this badly.
Thanks in advance
Some options to consider:
1) If you had a good continuous integration system with automatic build and deployment, would deploying every week be such an issue?
2) Have you considered MEF or similar which would allow you to substitute just a single DLL containing the new rules?
3) If the formula can be expressed simply (without needing to eval some code, e.g. A+B+C+D > E+F+G+H => J or K) you might be able to use reflection to gather the parameter values and then apply them.
4) You could use Expressions in .NET 4 and build an expression tree from the database and then evaluate it.
Looks like you may be well served by implementing the specification pattern.
As wikipedia describes it:
whereby business logic can be recombined by chaining the business logic together using boolean logic.
Have you considered something like MEF, then you could have lots of small dlls implementing various versions of your calculations and simply reference which one to load up from the database.
That is assuming you can wrap them all in a single (or small number of) interfaces.
I would attack this problem by creating a domain specific language which the program could interpret to execute the rules. Then put snippits of the DSL code in the database.
As you can see, I also like to overcomplicate things. :-) But it works as long as the long-term use is simplified.
You could have your program compile up your rules at runtime into a class that acts like a plugin using the CSharpCodeProvider.
See Compiling code during runtime for a sample of how to do this.