I have two entirely separate web (api) services.
One resembles the business case (bc) and the other's only concern is sending (and building) e-mails (ms).
So basically the BC sends all relevant data to the mail service.
BC ===== { Sender, Receipient, Subject, Template, Model } =====> MS
The mail service takes the template (razor template) and the model and builds the mail's content. It does the same with the subject which may also be a razor template.
The question now is... in order for razorengine to work properly... I need to specify unique names for my mail templates and I'd prefer not to trust the business case with this task. Because the client may choose a name which is already in use by another client (business case).
My solution right now looks like this:
string uniqueTemplateName = sha1(template); // bad idea?
string result = _razorEngineService.RunCompile(template, uniqueTemplateName, null, (object)model);
Using sha1(template) should do the trick, right? Are there any drawbacks to this?
You actually have several problems here depending on your requirements.
Initially it seemed like "clientname/templatename" would be a fit.
Usually you just use the path where the template came from (full directory path, database id).
Any kind of hash completely defeats the purpose of the caching layer for you to be able to notice when you need to recycle the current AppDomain because of stale templates. The default CachingProvider will always use the cached entry and changes will be ignored (no recompiles). But you can customize that to your needs. For example you could implement a strategy like: If a single template is edited more than 10 times the AppDomain is recycled. One can achieve this by implementing an ITemplateManager and an ICachingProvider and some AppDomain recycle code. How to do that is a bit out of scope for the question you asked, but you can look at the existing implementations.
This AppDomain recycle stuff is hard and defeating it with a hash seems like an easy solution, but if you have the requirement of changing template you need to think about it, because we can't abstract that away from you (because loaded assemblies cannot be unloaded). And depending on your users and your environment you might get into a situation where users can start a DOS attack to your service by filling up your memory. If you are fine with the performance you can look at the isolation API as well. With isolation you can use very simple approach like recycle the AppDomain every 1000 compiles (you still need to implement the notification yourself with a custom ICachingProvider or even simpler just count the number of times you are using RunCompile).
TL;DR Drawbacks:
Collisions (see the comment of Eric Lippert)
Unable to find/notice stale templates
-> DOS situations
Hope this helps,
matthid (Disclosure: A RazorEngine Contributor)
Related
I am building a hosted business SaaS application using MVC 4/C# 4. I'd need to have customer specific resource files, css, views, and business logic that leverage a base code layer as much as possible. How would each of these (resource files, css, views, logic) need to be structured to accomplish this?
I realize this is probably a very in depth answer...but I have no idea where to start or what to search for to begin to research this. Any pointers so I can research further?
Here are my initial thoughts on each:
Views
Use a Switch statement based on user to return different views.
CSS
Use switch statement in view to specify which css to load
Resource Files
I'm not using them now but need to implement, so not sure exactly how they work. From what I've seen you can specify a resource file at the class MetaData level, which is a compile time thing. Not sure how you would change this at the user level. I can see here, how to change it based on culture...but not by a user profile attribute (like the company they belong to).
This looks like a start...will review more.
Business Logic
In my services layer, I could implement switch statements...but that seems messy. Is there a way to create a new classes that override the base classes but only for certain users? Or putting these in a separate project/dll and only using that dll reference for a certain user?
I used to work on the IBM iSeries, and they had the concept of a library path that could be set by user at login. You'd have a custom code path that overrode the base code path libraries. Is there anything similar in MVC?
Data Localization
In my database, I have a table for Orders and another for OrderStatuses, which may be displayed in a drop down for the user to select a status. These statuses may be 'Open' and 'Closed'. But another customer may want that in Spanish...How would you handle this?
Any other considerations I am missing?
Use switch statement
Any time someone is writing object-oriented code and mentions a switch statement to control variable requirements, alarm lights begin to flash.
When you have similar but different requirements, polymorphism is your friend.
Without knowing full details of your requirements it is difficult to provide a specific answer, but consider using the factory pattern / dependency injection to provide objects appropriate to a specific user (or more probably, to the company associated with a specific user).
UI Layer
Generally speaking you could use a factory to return controller instances, based on a common subclass, that implement requirements for a specific user/customer and return views appropriate to that user.
I'm not well enough versed in the specifics of wiring routes in ASP.Net MVC to suggest how specifically to set that up, but it feels like the right approach. Perhaps another poster can shed more light.
Business Logic
This is a classic use of polymorphism, when requirements vary significantly. Alternatives to per-customer classes include configuration-driven behavior and rules engines. The best choice depends on your specific sitation.
Data Localization
Things like order status in the DB should not be bound to a text like 'Open'. They should be bound to a binary representation (e.g. an INT). Leave it to the View to translate that meaning into something specific to the user's language.
In a SaaS application we have developed we have clients who have their own private domains so being able to support something like that was a must. We had to be able to support:
www.mycompany.com/u/clientname
clientname.mycompany.com
www.clientname.com
On of the things we considered was how we could use a single deployment/code base to handle all of these clients. What we ended up with was a Base system that could be extended through the use of "plugins" which are basically class libraries named "APP.Clients.{ClientName}".
We wrote a custom ViewEngine that allows us to make use of these plugins to load Views, Controllers and even Controller Actions from the clients custom plugin to over-ride the base site.
What we ended up with is similar to what people call "portable areas" or basically external views and controllers in an Assembly.
Clients can share a common "network" database or they can be rolled off in to their own database. Most all of the config comes from reading the current URL and having logic that can determine which "client" it is and loading their settings and processing their customization.
Being able to load the client views required adding in additional search locations for Master Pages, Views and Partial Views (why we have a custom ViewEngine).
There is no simple answer and what works for one SaaS project may not work exactly the same for another. Your architecture will likely be similar but your business needs will dictate where your project takes you!
I have an existing MVC app which will be utlized by another user group in the near future. Both the existing and new user group/program will have independant data. I was just thinking to add flags in the tables to distinguish between the two user group/programs and do some routing when they access the application to pull up respective data.
Now when it comes to code customization, for instance one group/program wants to have extra fields on a page which the first group does not want or the process flow of the application is seperate between the two user groups.
If the above two scenarios will occur frequently, should I just do a new web and database instance rather than customizing the code for each program/user group. This way both of my customers/user groups will have flexibility to add different logic/fields to the application.
The only con I see with the non-multi tenant approach is the time effort by the developer to maintain two seperate applications. I am scared of adding contional logic to customize the same code base for each different user group/program. Cost of infrastructure is not an issue. Also I do not forsee this application to be used by more than 2 user groups/programs at any time. So what do you guys think which apporach i should take and why? thanks all in advance
P.S The users arent any ninjas who will try to hack the site to see the other tenants data. They are corporate users. Theyd rather not use this application but its part of the process so they have to use it.
It's worth taking a look at microsoft's article on multi-tenancy.
I'm also working on trying to design an mvc app with such an architecture where each client can have separate fields and customised screens.
The conclusion that I have come to is that using an IOC container with multi-tenancy support will probably make the whole thing a lot easier.
Autofac has built in multi-tenancy support.
In terms of having logic for clients in each view I believe that if you go down the IOC path you can have a controller for each tenant and in that case hard coding such client specific logic isn't necessarily as bad as it would be having it hard coded all into a shared controller. In essence I believe when writing a component that is for a particular tenant you can switch you mindset to writing as if that tenant was the only one using the system.
The other solution I have landed in for customising views is to use a variation of the RazorGenerator approach for compiled views where I have each tenants views compiled into a separate assembly and have created my own view engine (based on this) where I can swap out the assembly that I look for views in depending on a value in the routing parameters.
Of course I'm still exploring this approach and haven't fully flushed it out in order to find out where it may fall short.
If the difference in the 2 users' requirements is more than 10% of the screens/functionality then you better have 2 databases and apps. If it is expected to be less than 10% then just write separate actions (possibly with different prefixes or suffixes in Action names) for where the functionality differs.
I am trying to run multiple sites using single code base and code base consist of the following module (i.e. classes)
User module
Q & A module
Faq module
and each class works on MVC pattern i.e. it consist of
Entity class
Helper class (i.e. static class)
View (i.e. pages and controls)
and let say I have 2 sites site1.com and site2.com. And I am trying to achieve following functionality
site1.com can have User, Q & A and Faq module up and running
site2.com can have User and Q & A module live while Faq module is switched off but it can be turned-on if needed, so my query here is what is the best way to achieve such functionality
do I introduce a flag bit that I check on every page and control belonging to that module? It's more like CMS where you can turn on/off different features. I am trying to get my head around it, please provide me with an example or point out if I am taking the wrong approach.
You might want to look at Portable areas. You could design the code base so that each module is an area and then deploy them into the sites were they are needed.
After looking to some example and an extensive research I come to a conclusion that it depends upon 2 scenarios:
Scenario 1:
If in a case where there is only ten possible modules which are written once and require the whole update of the entire application if they need to be updated, then you can easily use checks which will propagate through the models and be used by the views to adjust the user interface (for example by showing or not the appropriate links in the web application menu).
Scenario 2:
If, instead, there is a case of many modules developed by many developers and it is unacceptable to require the update of the whole web application in order to update any of such modules, then look for plugins model, like for example the one used in FogBugz.
For making choice, consider following elements sorted by importance:
Maintainability: is it acceptable to modify the common code of the web application in order to change any of the modules?
Dependencies: are some modules dependent of others?
Performance: since we don't know the exact context, it's difficult to try to predict the impact of each solution. Maybe there will be
none, if you use heavy, cleverly designed caching.
Overall architecture: if there are reasons to do something monolithic (because of the interdependencies), the first solution
seems more appropriate; this is not the case if every module is
strictly separated from others.
My question is similar to "ASP.NET 2 projects to share same files", but with an ASP.NET MVC slant.
Basically, we have two sites, one being based mostly on the other (roughly 90% views, controllers, images, in the second are identical to the first). However, in some cases, the views may be different, or a controller in the second site may be different to the first.
Are there any simple ways of achieving this in ASP.NET MVC?
So far, we've looked at using linked files to have two totally seperate projects where the second project shares the files it needs from the first.
One problem with this approach is that most pages in the second project don't literally exist in the virtual directory, it makes debugging a pain - you have to publish in order to generate the files so you can debug.
Does anyone have any better approaches, or ways this approach can be simplified?
This article might help: http://dotnetslackers.com/articles/aspnet/storing-asp-net-mvc-controllers-views-in-separate-assemblies.aspx
Essentially, it involves creating your own WebFormViewEngine which tells MVC where to look for the Views.
If they are 90% the same and you want to keep them in sync as functionality evolves I would consider making them into a single web application and using the host header to differentiate and to change the images/links/text/functionality/etc. between the two sites.
You can do this in your BaseController: look at the host header and create a Brand object that every page and view has access to, just like it might have aUser object. That Brand object can include the name of the site, the canonical Url for the site, the location of the image directory for that brand, boolean values to turn certain features on or off, ...
Now in a Controller you can just ask if (Brand.SupportsPageX) {...} to decide what to show next. And if you make the brand object part of your base view model or put it in the view collection you can have views that use the brand's name, image directory, ... to customize how they look.
Put as much as possible into a shared non-UI library project. I do that on every project that I work on this, increased testability, shared code with Windows Services, and a host of other reasons.
I've found that if you're aggressive with this then quite often over two-thirds of the project would be in the non-UI shared library.
After doing this, you can take things a step further and create a second library with some shared MVC/UI elements.
Depending on your opinion of it, RenderAction may help a bit here. As you know, RenderAction will allow you to group up those controller/view components and pass in variable arguments at runtime.
A project I'm working on currently has a similar requirement and we have started looking at using portable areas. I personally haven't delved very deeply into them at the moment, but it may be worth you taking a look.
I've been working with areas to create multiple websites that I can host with one hosting account. I would think you could use a similar approach. By implementing the common functionality in the base project, it will be available to each area. You can also override any of the base views or controllers by implementing them in the area. It may require some tweaking of the ViewEngine and Routing but I think it could be done.
Im new to the DDD thing. I have a PROFILE class and a PROFILE REPOSITORY CLASS.
The PROFILE class contains the following fields -> Id, Description, ImageFilePath
So when I add a new Profile, I upload then image to the server and store the path to it in my db.
When I delete the profile, the image should be removed from my file system aswell.
My Question:
Where do I add logic for this. My profile repository has a Delete method. Should I add this logic here. Or should I add a service to encapsulate both actions.
Any comment would be appreciated...
Thanks
You have two different "actions" related to the images. You have a "physical" process and a "logical" process. The logical process is persisting the information about the image into the domain repository, since it is part of the domain. The physical process of add (and delete) are a prerequisite to the logical process.
Taking a step back, the physical process is completely independent of the logical process, but the opposite is not true. You obviously do not want to persist meta-information about the image (in the domain) if the image was not saved. Also, you don't want to remove the information from the domain if you cannot remove the physical file.
The domain should contain the information required to remove the logical instance of the image from the datasource. Think of the domain as a physically separate application. In this case, the domain has no actual knowledge that the data it is persisting has anything to do with a physical file. Make sure to keep it this way.
Generally, I have my entities in an assembly, then my repositories and domain services in another. The application services live outside of the domain model, but leverage it to do its work. So application services use one or domain services or other application services and domain services can use one or more repositories.
Keeping this in mind, you have two places for the actual deletion logic, and a third place to coordinate them. Here is how it would work if I were doing it. The domain service will leverage the repository for the logical delete from the underlying datasource (as well as a retrieval which you will need, as well). It is not aware of anything else other than working with the domain object instance. I also would have an application service (outside of the domain) which specifically dealt with removing the physical instance. For argument sake, I will assume you have an "ImageRepository" class and an "ImageServices" class, which contain your domain repository and your domain services, respectively. Your ImageServices needs a Delete() method, as well as whatever Find() methods you are using. I usually explicitly call the find methods as FindBy...() (i.e, FindByKey(), FindByName(), etc.).
You don't want to remove the logical instance if you haven't been able to remove the physical instance, so make sure you have a means of measuring success of the removal operation for the physical image. I would probably go with some sort of a custom exception in this case (since I would consider deleting a file to be a standard operation that should not commonly fail). This usually falls in the realm of "management". So usually I have an application service named something like "ImageManagementService". For simplicity sake, this service (since it is part of the application and not the domain) can have a private method to do the physical delete. Let's call it "DeleteImageFile()".
The third place is a coordination of these two operations, also as an application service. I would just make this the public method in the "ImageManagementService". We can call this one "RemoveImage". This application service will do the following:
Retrieve the instance information from the domain services (a passthrough call to your repository).
Use the instance information to locate the physical file and remove it (the first application service mentioned, again).
If the physical removal is successful, delete the instance (back to the domain service, facading the repository again).
So, what happens is the application itself calls the "RemoveImage()" method from the "ImageManagementService" instance. Internally, "RemoveImage()" first calls the "FindBy..()" from the domain's "ImageServices" to get an instance from the domain. The filepath is used from there to call to the private "DeleteImageFile() method in the "ImageManagementService" instance. Upon success, it will then call the "Delete()" methods in the domain's "ImageService", which is acting as a facade to your repository.
I think it is very important to focus on the separation of concerns in this case, because if you have an explicit separation (which you can do with different assemblies) you will become comfortable with knowing which kind of logic can go in which place. I highly recommend the Evan's book. Also, for a quick hit on the SOC concept as it relates to DDD, I recommend taking a look at Jeffrey Palermo's three part series on the "Onion Architecture".
Just a couple of notes as to why you would use a domain service instead of calling the repository directly from the application service. Primarily, the repository has more complicated instancing then the domain service. Remember, it is mostly a facade, but might have additional logic that does not fit in anywhere else in the domain. A good example of this might be if you wanted to enforce a unique filename. The domain object itself has no knowledge of other domain objects in other aggregates directly, so the domain service might check for an existing instance with the same name prior to a save operation. Very handy, indeed! Also, a domain service is not limited to a single repository. You can have a domain service coordinate efforts between multiple repositories. If you have overlapping aggregates, you might need to call work with two related aggregate roots at the same time. you can do this in the domain service, keeping that sort of logic in the domain and not bleeding into the application.
Hope this helps. I am sure that there are other ways to do this, but this is the way that I have found success in my own applications with similar scenarios.
#joseph.ferris: "Generally, I have my entities in an assembly, then my repositories and domain services in another. "
Personally, I prefer to see assemblies as a unit of deployment, not a separation of concerns design tool. For that, I'd rather use namespaces.
Ensuring no cyclic-dependencies (between those namespaces) that way is harder, but tools like NDepend can help out.
On a first approach, I think I would opt for the most simple approach, and delete the physical image from disk inside the ImageRepository.
It is maybe not the most 'correct' or 'pure' solution, but it is the most simple one, and this conforms to the 'choose the most simple solution that works' adagio.
When, in a later phase of the project, you feel that this solution is not good, and you feel you need a more complex (and maybe more pure) solution like the one proposed by joseph.ferris, then you can always refactor it.
It is easier to refactor a simple solution, then to refactor a complex solution. :)