I want to offer a tumblr-like functionality where you can select a template, and optionally customize the HTML of your template in the browser and save it.
Current stack: Mongo, Sinatra (for REST API) for prototype. Will likely be moving to a compiled, statically-typed language later.
Wondering how best to accomplish this. Options I've considered:
Store the HTML in mongo, and duplicate it for all user accounts. So the HTML for the template you choose gets written into your account. Obvious cons of space inefficiency and need to update all users that use that template (if un-customized - you customize it it becomes your own and I won't ever touch it) if the template changes.
Store the templates in templates collection, and put custom templates either into this same collection or into the user collection with the owner of the template. User references a template id. This is quite clearly better than 1 I believe. Especially because I won't need to pull the template every time the user object is pulled.
Some third party library? Open to suggestions here.
File system.
I will need to package up these templates (insert js and stuff the user shouldn't be exposed to) and then serve them. Any advice on how best to approach this is greatly appreciated.
Your approach will depend on how often you foresee people customizing the template versus just going with a standard. How about a hybrid approach?
That is, have a field in the user document that is created lazily (on use) that either stores the custom template, or maybe a diff from one of the standards (not sure about the level of customization you are planning to allow).
Then you can have the template field you describe in 2 above, with a "special" setting for custom templates. While you still have the concern about pulling a template each time, you do have the advantage of knowing that these are some of your more dedicated users - saving a trip to the DB might be advantageous, or you might not care.
If you don't care about 2 trips to the DB for every user, then you take approach 2, add the custom templates to the templates collection and simply reference the new ID for each user that customizes.
It's a balancing act - is the extra data overhead in terms of pulling the template each time worth saving a round trip to the DB or do you want efficiency in terms of the data you get each time at the cost of multiple queries to the DB - only you can answer that one based on how you design your app and how people use it.
For the linked approach you might want to take a look at Database References and Schema Design in the MongoDB docs.
Related
I have this idea of generating an array of user-links that will depend on user-roles.
The user can be a student or an admin.
What I have in mind is use a foreach loop to generate a list of links that is only available for certain users.
My problem is, I created a helper class called Navigation, but I am so certain that I MUST NOT hard-code the links in there, instead I want that helper class to just read an object sent from somewhere, and then will return the desired navigation array to a page.
Follow up questions, where do you think should i keep the links that will only be available for students, for admins. Should i just keep them in a text-file?
or if it is possible to create a controller that passes an array of links, for example
a method in nav_controller class -> studentLinks(){} that will send an array of links to the helper class, the the helper class will then send it to the view..
Sorry if I'm quite crazy at explaining. Do you have any related resources?
From your description it seems that you are building some education-related system. It would make sense to create implementation in such way, that you can later expand the project. Seems reasonable to expect addition of "lectors" as a role later.
Then again .. I am not sure how extensive your knowledge about MVC design pattern is.
That said, in this situation I would consider two ways to solve this:
View requests current user's status from model layer and, based on the response, requests additional data. Then view uses either admin or user templates and creates the response.
You can either hardcode the specific navigation items in the templates, from which you build the response, or the lit of available navigation items can be a part of the additional information that you requested from model layer.
The downside for this method is, that every time you need, when you need to add another group, you will have to rewrite some (if not all) view classes.
Wrap the structures from model layer in a containment object (the basis of implementation available in this post), which would let you restrict, what data is returned.
When using this approach, the views aways request all the available information from model layer, but some of it will return null, in which case the template would not be applied. To implement this, the list of available navigation items would have to be provided by model layer.
P.S. As you might have noticed from this description, view is not a template and model is not a class.
It really depends on what you're already using and the scale of your project. If you're using a db - stick it there. If you're using xml/json/yaml/whatever - store it in a file with corresponding format. If you have neither - hardcode it. What I mean - avoid using multiple technologies to store data. Also, if the links won't be updated frequently and the users won't be able to customize them I'd hardcode them. There's no point in creating something very complex for the sake of dynamics if the app will be mostly static.
Note that this question doesn't quite fit in stackoverflow. programmers.stackexchange.com would probably be a better fit
I'm building a multi-lingual web application using the MVC pattern as the starting position. The application has a number of forms that users will be interacting with and many of these forms will have fields that do a lookup from a database table, 'Province' for example.
If I need the options in these lists to be displayed in the users' language on the screen, I can see a couple of ways to do this:
In the model. When querying the model, I can provide the language that I desire the results to be returned in. This would allow translations to be used everywhere that data from the model is displayed without changes. However, this also means that the Province model in my example (plus all other application models) now need to know how to do language translations.
In the controller. I can query the model in the controller action as usual and then create a 'Translator' object that I can pass the results into before completing the action. This would imply that each controller action would potentially be duplicating the same translation code, violating the DRY principle.
In the view. Since the presentation of the application is generally expected to exist in the views, and the language of the user doesn't impact the business logic of the system, an argument could be made that language translations belong here. Especially considering that a page could also contain static content that will need to be translated. The downside to this is that it would complicate the views somewhat, especially for the front-end designers who will have to work around the new translation code.
Is there an accepted best-practice for where text translations belong in the MCV pattern for web applications? Does this change at all if I were to be loading the select list options via an AJAX call instead of at page load time?
Thanks for the help!
The best place to handle it is in the view. Your question only references dynamic data from the database, but you also have to handle the static information in your views as well. Best to handle both of those in the same place. A common practice in MVC for handling multiple language is resource strings, separate views for each language, or a combination of both. For information from the database resource strings would work well. You would store a token in the database for the options in the list (that token could be the English translation) and the view would get the appropriate translation from a resource for the specified country/locale. There is a good detailed explanation on this approach in this blog post.
If you need to translate part of your UI, then I would create a helper method that would read a resource file and output a translated string for that resources. E.g.
#Translate("NewUserHeading")
So regarding the UI, it makes sense to handle this in the UI.
If the data that you are going to translate at some point might be shown in a Flash client, or a mobile app, then it should be translated by a server and it should have nothing to do with your MVC application.
Honestly, any interaction with a database should be handled in the model, and that's the only thing handled in the model. Interpreting/organizing that data should be handled in the controller. I guess more information would be need as to where this translation is coming from and how that works to really give a solid answer.
The view will just display strings from a resource file. Including the correct resource file for the locale should do it. In Web applications, it's often a single language JS file defining the UI strings per locale, e.g, strings.en-us.js, strings.pt-br.js and so on.
Some strings do come from the server dynamically, the controller doesn't need to know about it, the model should just grab the localized strings and return is as part of the data request.
So it's either in the view (if it's static) or in the model, (if it's dynamic). Controllers should just translate data from the view to the model and from the model to the view
Another very important thing to consider is WHEN to Translate. Using a once-per-each-translation method like #Translate("NewUserHeading") is fine if you only have 100 translations on your page, but what if you have more?
Because think about it, translation is based upon language choice and that only happens once-per-page or even once-per-session. The way that the Kendo UI people do it in their demo is that way, when the User clicks a new language a new set of server files is loaded. That would mean having something like:
/src/html/en-us/
/src/js/en-us/
/src/html/es/
/src/js/es/
etc..
Check it out at https://demos.telerik.com/kendo-ui/grid/localization
It's a trade off of more work for better performance. The ultimate use-case of translation right now is https://www.jw.org/ with over 900 languages!
I work on an ASP.NET MVC 3 application where branches in version control have been created for each country. This makes it difficult sync changes between the branches and the problem will increase as the number of countries increases. I have read about branching by abstraction but have never actually used it so I'm struggling to comprehend how this would be actually be implemented in a reasonably complex project.
Can anyone explain how branching by abstraction can be done for an ASP.NET MVC application where the abstraction is a country, and the application is a n-tier type affair with service and data layers?
A few of the things I can't get my head round are:
Abstracting view stuff. E.g. The aspx/cshtml files, javascript, css
etc.
Abstracting controllers
How do you manage the extra complexity of having all your for code
every country in one branch? (Note, by one branch I mean the default branch, mainline, whatever you want to call it)
How you you manage feature toggles for each country? E.g. Potentially you could have many many features for each country that were not ready for release and controller by a toggle)
How do you select the appropriate country when deploying?
How do you run unit tests for country specific functionality?
UPDATE
I'm not just talking about language changes. Much of the service layer logic for each country is the same, but in certain key areas it's different, likewise for the data layer. Also view content and layout can vary, javascript can vary and controller logic can vary.
Why do you use branches to handle localization? imho it's madness.
There are several ways to do localizations without having one code base per language.
For instance. By making your own view engine on top of an existing one you can load views from external assemblies. Or you can create one view per language.
You can also use string tables in your views to make them localized.
Abstracting view stuff. E.g. The aspx/cshtml files, javascript, css etc.
Javascripts: I have one javascript with all my logic which uses variables instead of strings to show messages. In this way I can load another javascript before the logic script (for instance myplugin.sv.js before myplugin.js to get the swedish language.
The most common way for aspx/cshtml files is to use string tables in them.
Localize css? Why?
Abstracting controllers
huh? Why? Use string tables here too.
How do you manage the extra complexity of having all your for code every country in one branch?
Don't use branches.
How you you manage feature toggles for each abstraction?
huh?
How do you select the appropriate country when deploying?
Use the same site for all languages. Either use the IP address, Accept-Language http header or the user's language preference to select language. Language is specified by setting Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture
How do you run unit tests for country specific functionality?
Don't. The logic should be the same.
Update in response to your comment
I've written my fair amount of systems where content is dynamically loaded into the application/service. I've never used different code bases even if different customers use different features in multi-tenant systems (SaaS).
First of all, you need to accept two things:
a) All content is loaded at all time (not talking about translations, but features).
b) Use proper/standard localization methods, but no need to translate all features to all languages.
What you do is simply control which content to load and use standard techniques to get translated features. The control is made by either checking the current language (Thread.CurrentThread.CurrentCulture.Name) or any homebrewn control.
Ask new questions to get more details.
Update 2
I wouldn't rely on the IoC to provide language specific features, but use reflection and a FeatureProvider class to do that for me.
For instance, let's say that you have a feature called ISalaryCalculator which takes into account all local tax rules etc. then I would create something like this:
// 1053 is the LCID (read about LCID / LocaleId in MSDN)
[ForLanguage(1053)]
public SwedishSalaryCalculator : ISalaryCalculator
{
}
And have a FeatureProvider to load it:
public class FeatureProvider
{
List<Assembly> _featureAssemblies;
public T GetLocalFeature<T>()
{
var featureType = typeof(T);
foreach (var assembly in _featureAssemblies)
{
foreach (var type in assembly.GetTypes().Where(t => featureType.IsAssignableFrom(t))
{
var attribute = type.GetCustomAttributes(typeof(ForLanguageAttribute)).First();
if (attribute.LocaleId == Thread.CurrentThread.CurrentCulture.LCID)
return (T)Activator.CreateInstance(type);
}
}
return null;
}
}
And to get the feature (for the current language):
var calculator = _featureManager.GetLocalFeature<ISalaryCalculator>();
var salaryAfterTaxes = calculator.GetSalaryAfterTax(400000);
In a simple scenario (CMS/not much or shared business logic) you are dealing with just content in different languages and:
Layout (left to right vs right to left) - you will have two CSS files
Localized (translated) content
Layout CSS can be in separate files and be pulled in depending on the User Account's culture or site region setting.
Localization can reside in different assemblies - one for each culture or in separate string table files (as already mentioned).
In a more complex scenario, where you are developing an application for sensitive cultures and regions where:
You have to be careful about the content you display - for example an image can be very offensive in one country but perfectly fine in another country.
Different business logic (e.g. think financial application, etc)
Most of the content issues you can solve with CSS, but even if you need heavily customized views as has already been mentioned you can create a view engine that pulls a view file based on the current culture (e.g. Index.en-Us.cshtml, Index.ru.cshtml, etc)
For the different business rules you must have a good design and architecture utilizing Inversion of control (e.g. dependency injection) and patterns such as the Strategy, state, Template method, etc. Given that you have that in place you will be able to create an IoC container project/assembly per culture at run time and your UI will be unaware of the difference since it will be simply consuming some services defined by those interfaces.
Slightly more tricky if your ViewModels are significantly different between cultures, but if they are you probably want to maybe split View + Controller per culture in different assemblies and again use IoC to configure the routing at run time initialization.
Clearly deploying multi-cultural sites is more complex than non-such and no matter which way you go (site instance per culture or one site instance for all cultures) you will probably want to invest in some tooling to be able to script multi-culture deployment.
And last - regarding the unit tests - if you already have a good IoC based design testing per culture will be a matter of using and configuring the right dependency container prior to running a set of unit tests.
With such a setup the teams of developers should be working in relatively self-contained environment, since your project will be logically and physically be partitioned to support multiple teams working on separate parts of it at the same time. It also shouldn't matter whether on branches or trunk/head. Of course if everything is a big mess in just a few projects and people have to constantly merge in - you are in a very bad state and your future isn't bright.
Final words: It's not about branching - it's about design, architecture, partitioning (solutions, projects and assemblies) and last but not least about automation (build and test).
This is a little off topic, but I believe you're heading in a more difficult direction than you need to. Localization is built into ASP.NET and the MVC framework can take advantage of it also.
The short story is that you basically make a resx for each language you'd like to support. You then use Resources.Global.YourLocalizedStringPropertyName in your views.
This blog post is the long story. Scott Hanselman goes over javascript localization and other finer points. It's definitely worth a read and will probably save you incredible amounts of work to use the built in functionality instead of building it yourself:
http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx
In an upcoming project, we will be creating forms for citizen's to fill out to start the process of applying for the requested license or permit. As one can imagine, a form tends to change often. I would prefer to plan this into the application to avoid making changes on a yearly/monthly/"the big boss want's it yesterday" basis.
My searching has shown me some examples based on the object passed to the view, but those would require coding changes. Others use XML, but never seems to go through the entire process from creating the from to storing the inputted data into the database. It isn't that I need hand holding the entire way; it's that this is something completely different for me and I want some guidance to get me in the right direction. I am thinking along the lines of how these survey sites (like SurveyMonkey) create dynamic polls.
Is there any tools, utilities, tutorials, or books that may cover this quite well?
I would imagine you would probably want to take advantage of Display / EditorTemplates. You would define an interface IQuestion or something, and then have a bunch of different form options that implement that interface. So your model would have a List<IQuestion>, and then for each question in the list, Html.EditorFor(item) or so.
Then some kind of standardized way of storing the answers into a table (perhaps a unique save / load method on IQuestion. That's my take anyways. You could define the questions via DB and then your models could have varying counts (and elements) in the List<IQuestion>. Just run a DB script (or some kind of admin page) and you could dynamically change the form displayed.
I am creating a front-end for a data collection web application. Operators using the data collection application will log data for a dozen different projects, with each project requiring different fields. There are some common fields (like name, address... etc) but then each project also has custom fields for extra data that needs to be collected. Some projects require dozens of extra fields, while some projects require only 1 or 2 fields. Can anyone think of a "clean" way to handle this situation? I don't want to create an input page for each project, and some people are tossing around the idea of doing UI templates in XML. Any guidance would be much appreciated.
XML would provide a neat solution to your problem. Depending on the user choice, ask the user to fill more fields. From your problem statement its looking that you know how many projects need extra fields and which do not. If you know this data then feed this data into a database and then accordingly generate your form page. However even if the data is available dynamically with the use of an interactive javascript and ajax you can easily achieve a neat solution.