How to setup single-code multiple-database ASP.NET SaaS application - asp.net

I am building a SaaS application and I would like to retain the single code base I have. I would like to be in separate sub-domains cust1.saascompany.com, cust2.saascompany.com, etc.
However, I don't have any TenantID's and would prefer for multiple reasons to stay with separate databases for each customer (primary one is that it's already coded that way and doesn't make sense to change it until usage warrants). The database has the user login membership within it.
I'm guessing I would need separate web.configs for connection strings? Or should I create a separate database that stores all the connection strings and any application level variables/constants? Eventually, I would like to be able to automate this provisioning (again, when usage warrants it).
Are there some articles or posts that anyone can point me to regarding how to set this up with steps? I haven't been able to find what I'm looking for.

Technically, this is simple. We do this for years. Although we use a different convention (my.domain.com/cust1, my.domain.com/cust2 plus url rewriting) this doesn't change anything.
So, this is what you do. You create an abstract specification of a connection string provider:
public interface ICustomerInformationProvider
{
string GetConnectionString( string CustomerId );
... // perhaps other information
}
then you provide any implementation you want like:
public class WebConfigCustomerInformationProvider : ICustomerInformationProvider { ... }
public class DatabaseConfigCustomerInformationProvider : ICustomerInformationProvider { ... }
public class XmlConfigCustomerInformationProvider : ICustomerInformationProvider { ... }
and you map your interface onto the implementation somehow (for example, using an IoC Container of your choice).
This gives you the chance to configure the provider during the deployment, for example, a one provider can be used by developers (reads connection strings from a file) and another one in the production environment (reads connection strings from a database which can be easily provisioned).
If you have other questions, feel free to ask.

Related

ASP.NET Identity - Steps for custom authentication

Envrionment: Visual Studio 2013, ASP.NET MVC 5
On the new MVC5-based project I will be working on, I need to use a custom database that stores usernames, passwords, and roles in its own way. I am searching the Internet to look for an example for custom authentication. Looks like the old-style "membership provider" classes have been replaced by the new "Identity" mechanism.
However, finding a good step-by-step example has proven to be futile. There are a few links (published this year) that talk about implementing custom IPrincipal and DbContext classes. Some other links talk about implementing IUserLoginStore and IUserPasswordStore. A few others hinted on implementing IUser, IUserStore interfaces.
Maybe the last option is what is needed. Can someone please guide me with the steps or point me to any link that has a simple example? Something like:
Implement MyUser based on IUser
Implement MyUserStore based on IUserStore
Modify web.config to use MyUserStore
Remove DefaultConnection from web.config as it is not required
Regards.
First, stop. Stop thinking about "custom authentication". You don't need custom authentication, you just need custom storage of authentication data.
ASP.NET Identity has abstracted out the storage mechanism of authentication from the process of authentication. There are several interfaces that follow the pattern IxxxStore.. Such as IUserStore, IRoleStore, etc...
You can find more information about this here, along with custom implementations for various databases which you can probably convert to your own needs.
http://odetocode.com/blogs/scott/archive/2014/01/20/implementing-asp-net-identity.aspx
As an example, here is a RavenDB implementation that uses all the various interfaces in a single class.
https://github.com/tugberkugurlu/AspNet.Identity.RavenDB/blob/master/src/AspNet.Identity.RavenDB/Stores/RavenUserStore.cs
However, all this assumes you really truly a need to store data totally differently. If you just need to store the data in different columns, then it may simply be as easy as overriding OnModelCreating in your IdentityContext and changing the names of the columns in use.
ad.1.
public class ApplicationUser :IUser
{
public string Id
{
get;
set;
}
public string UserName
{
get;
set;
}
}
ad.2.
public class MyStore : IUserStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser>, IUserEmailStore<ApplicationUser>
{
... //implement all interfaces here
}
ad. 3.
Now you can create your applicationUserManagerService (you will need IdentityMessageService, and IDataProtectionProvider):
var applicationUserManagerService = new ApplicationUserManagerService(new MyStore(), emailService, dataProtectionProvider);
Try to use IoC and register your IUserStore (I did it this way - link below):
unityContainer.RegisterType<IUserStore<ApplicationUser>, MyStore>();
check also my answer here (i'm using int as UserId there):
AspIdentiy ApplicationUserManager is Static, how to extend so it participates in my IoC framework?

Where to put entity 'helper functions'?

I am having trouble understand a key concept of Symfony 2.
I am working on a website where users can create content which then can be sent to other people, using a secret url. Something like www.yoursite.com/{secret-identifier-string}.
I plan on doing this as follows:
Persist the user's content.
Create the identifier string containing the content id and the creation timestamp (or any other content which will never change again, as extra safety feature) with a two-way encryption method (like mcrypt_encrypt).
Create the link and display it to the user to give it away
Whenever a url is called, the identifier string will be decrypted. If the provided timestamp matches the corresponding value of the content id row, the page will be displayed.
My questions are:
Would you consider this a good procedure in general?
Outside Symfony2 I would create helper methods like getIdentifierString() and getContentPageLink(). Where do I put the corresponding code in Symfony2? Does it belong inside the entity class? If so I am having problems because I am using a service class for encryption. The service is only available in the controller.
Thanks a lot!
With all due respect to DI and service oriented design, namespacing and all the good stuff we benefit from,
I still refuse to type or read:
$this->mysyperfancyservice->dowhatevertheseviceissupposedtodowith($the_entity);
where a simple
do($the_entity);
is all I need on 150 instances across my project, where do is something everyone working on the project will know about.
That is what helper is meant for - readability and simplicity. As long as it doesn't depend on other services though.
My solution for that is in basic Composer feature:
"autoload": {
...
"files": [ "src/helper/functions.php" ]
}
I put a very limited number of extremely useful functions in src/helper/functions.php file, and add it to project like that.
In order for the function to become available project-wide, it is required to run:
composer dump-autoload
The general idea is that you create "helper classes" rather than "helper functions". Those classes may have dependencies on other classes in which case you'll define them as a service.
It sounds like your methods do have dependencies (on encryption) so you can make a new service that is responsible for generating links. In it's constructor it would take the encryptor and the methods would be passed the entity to generate a link/string for.
for example, your service:
<service id="app_core.linkifier" class="App\CoreBundle\Linkifier">
<argument type="service" id="the.id.for.encryptor"/>
</service>
and class:
class Linkifier
{
private $encryptor;
public function __construct(Encryptor $encryptor)
{
$this->encryptor = $encryptor;
}
public function generateContentPageLink(Entity $the_entity)
{
return $this->encryptor->encrypt($the_entity);
}
}

Creating Global Variable For Web Application - ASP.NET

i'm building my web application to connect with db.
so far i have managed to deal with it, (although i didn't build BLL & DAL).
i have a table which has column "id". i know there is a way to declare it in the SQL Server to be incremented automatically. ( but i don't want it).
i want to declare a global application variable that will hold the value.
i have 2 questions:
how i declare it?
where i create it and initialize it ? (i have several login pages).
THANKS!
p.s
it would be helpful if someone will tell me how do i build the DAL with my stored procedures?
and for what i need yo use BLL which i cant do in the DAL?
You can use the Application object - it is part of the HttpContext and is directly accessible on any page.
If you don't want to use it, you may want to write a Globals class (or whatever name you like) that holds static members.
public class Globals
{
public static int Counter { get; set;}
}
// accessed from other classes:
Globals.Counter++;
Either approach will not work of you have a web farm or several web applications and will not survive restarts.
Regardless of these options, the right solution (even if you don't want to use it - can you explain why?), is to use the ID field with the IDENTITY clause.
Storing the variable is the easy part. Managing your own ID generation and the contention and concurrency issues is the hard part. Good luck.
There really is no such thing as a global variable in ASP.NET. Remember, HTTP is stateless.
The closest you can come is storing something in the Application object:
Application["myvar" ] = x;
x = Application["myvar"];
But even here, this variable is lost when the app needs to restart, which it can do from time to time.
A much better solution for what you describe is a database value.
Incrementing an integer and then throwing that incremented ID into the db is fraught with danger. Multithreading? What happens when the application bounces? Do dev and prod deployments share the same set of numbers?
It sounds like you need a globally unique identifier and can be created outside of the database. That sounds like a job for a GUID. Sure, it takes up more space in the db, but it probably isn't the worst thing you are going to do to the database.

Suggestions In Porting ASP.NET to MVC.NET - Is storing SiteConfiguration in Cache RESTful? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I've been tasked with porting/refactoring a Web Application Platform that we have from ASP.NET to MVC.NET. Ideally I could use all the existing platform's configurations to determine the properties of the site that is presented.
Is it RESTful to keep a SiteConfiguration object which contains all of our various page configuration data in the System.Web.Caching.Cache? There are a lot of settings that need to be loaded when the user acceses our site so it's inefficient for each user to have to load the same settings every time they access.
Some data the SiteConfiguration object contains is as follows and it determines what Master Page / site configuration / style / UserControls are available to the client,
public string SiteTheme { get; set; }
public string Region { private get; set; }
public string DateFormat { get; set; }
public string NumberFormat { get; set; }
public int WrapperType { private get; set; }
public string LabelFileName { get; set; }
public LabelFile LabelFile { get; set; }
// the following two are the heavy ones
// PageConfiguration contains lots of configuration data for each panel on the page
public IList<PageConfiguration> Pages { get; set; }
// This contains all the configurations for the factsheets we produce
public List<ConfiguredFactsheet> ConfiguredFactsheets { get; set; }
I was thinking of having a URL structure like this:
www.MySite1.com/PageTemplate/UserControl/
the domain determines the SiteConfiguration object that is created, where MySite1.com is SiteId = 1, MySite2.com is SiteId = 2. (and in turn, style, configurations for various pages, etc.)
PageTemplate is the View that will be rendered and simply defines a layout for where I'm going to inject the UserControls
Can somebody please tell me if I'm completely missing the RESTful point here? I'd like to refactor the platform into MVC because it's better to work in but I want to do it right but with a minimum of reinventing-the-wheel because otherwise it won't get approval. Any suggestions otherwise?
Edit: Areas?" Would it be a viable option to use ASP.NET MVC 2 Areas, where each Area represents a different site, complete with css, javascript, etc.?
I agree with the accepted answer. Because this answer did not explicitly go into your question about being RESTful or not I would like to add something about that (1). And also go into your question about area's (2).
0. MVC.NET?
But first I want to say that for MVC.NET, the official term is ASP.NET MVC. With ASP.Net you probably meant ASP.NET Webforms. The full terms more clearly indicate MVC is still just an extension of ASP.NET. Then it's less of a surprise that you can also mix and match MVC views and 'old' .aspxpages in one and the same project, if you so choose. This CAN be an easy way to port a project from WebForms to MVC, by allowing stuff to migrated step-by-step over a periodand getting new stuff out there e.g. the Agile way. Note to be careful to update routing/URL's for users/SEO as you go).
1. Using cache
Using the cache for per-domain customization is indeed RESTful enough. I assume you mainly had question about 'stateless' property of true RESTful services. Only if you also did per-user customization with your SiteConfiguration object would you violate that. When config only differe changes per domain, the state/config is in-a-way encapsualted in the URL (e.g. the domain name) so the state/config travels to and from the user, and your service itself is stateless.
Also using .NET's Cache object as you propose instead of an alternative like the Application object has some advantage according to this SO article.
I personally dislike using the cache for basic acrchitectural things however, because it is untyped. So you have to cast all stuff from the cache. I'm nitpicking here because you have only one big configuration object, so this only has to be done once, and all the stuff in it is nicely typed. But still..
The site I've been working on lately also has per domain customization, but that is basically just the language the site is shown in. So directly at the beginning of each request (global.asax's Begin_Request) we simply set the current CultureID on the CurrentThread (this thread handles the incoming HTTP request for one domain, and serving the response). We can then show english for our-domain.com, French for our-domain.fr, etc. So the culture has a direct one to one mapping with the domain of the current URL. Localization logic can then be done using .resx files. We also have some limited conditional logic on this current cultureID spread throughout our code to allow having some parts being not available, or sending localized e-mails and other not directly request related stuff.
Long story, but spreading the per-domain specifics/config throughout your code in a similar way, based on current domain, would be an alternative. But this would not really reuse the existing logic as you say you wanted. SO I will mention one last alternative.,
You could use your existing SiteConfig class but then use a set of simple static variables (instances of the SiteConfiguration class) for each configuration type that you have. That way everything is neatly typed. You can map the domain name in the URL to the matching static configuration object at the beginning of each request as I indicated, and then access the config of the current request. That is assuming you have a managable number of sites, that are each quite distinct, and that and you don't have to be able to load configuration dynamically from a database or something. Note that using static variables they can still be loaded at app startup from either DB, or from web.config/appSettings (or something else). When you use web.config/appsettings it has the advantage that the site would automatically reload/restart with the new config when you change it.
2. Using Area's
About using area's for different sites instead of different domains. It depends on what you want. But I see area's more for allowing having different parts on one site, that are functionally different. E.g. that don't have much in common and therefore don't share any generic code. Area's basically allow you to put a group of somehow related controllers, models and views into one area of the site. And then via area routing, separate the different functionalities within one part of the site that is apparent to users also via starting with the same URL.
From what you say, it seems meer that all your sites share the same generic code, but are just customized through some configuration. So I don't think area's match your problem.
Setting this information in your cache is just fine but anytime your application recycles it will need to be reload which usually isn't a problem. I think this follows the model since each request is providing you with the info you need to pull from the cache since it is based on the requests domain and you don't really need to look it up in a DB or make a costly call to build it except for the first time.
You could also consider moving this data to your web.config file but I am assuming there is one site with many domains pointing to it that you want to customize?
Just make sure your indexing the cached data with the site it's associated with and accessing by that index because all domains pointing to one app will use only one cache.

NHibernate compromising domain objects

I'm writing an ASP.NET MVC application using NHibernate as my ORM. I'm struggling a bit with the design though, and would like some input.
So, my question is where do I put my business/validation logic (e.g., email address requires #, password >= 8 characters, etc...)?
So, which makes the most sense:
Put it on the domain objects themselves, probably in the property setters?
Introduce a service layer above my domain layer and have validators for each domain object in there?
Maintain two sets of domain objects. One dumb set for NHibernate, and another smart set for the business logic (and some sort of adapting layer in between them).
I guess my main concern with putting all the validation on the domain objects used by NHibernate. It seems inefficient to have unnecessary validation checks every time I pull objects out of the database. To be clear, I think this is a real concern since this application will be very demanding (think millions of rows in some tables).
Update:
I removed a line with incorrect information regarding NHibernate.
To clear up a couple of misconceptions:
a) NHib does not require you to map onto properties. Using access strategies you can easily map onto fields. You can also define your own custom strategy if you prefer to use something other than properties or fields.
b) If you do map onto properties, getters and setters do not need to be public. They can be protected or even private.
Having said that, I totally agree that domain object validation makes no sense when you are retrieving an entity from the database. As a result of this, I would go with services that validate data when the user attempts to update an entity.
My current project is exactly the same as yours. Using MVC for the front end and NHibernate for persistence. Currently, my validation is at a service layer(your option 2). But while I am doing the coding I am having feelings that my code is not as clean as I wish. For example
public class EntityService
{
public void SaveEntity(Entity entity)
{
if( entity.Propter1 == something )
{
throw new InvalidDataException();
}
if( entity.Propter2 == somethingElse )
{
throw new InvalidDataException();
}
...
}
}
This makes me feel that the EntityService is a "God Class". It knows way too much about Entity class and I don't like it. To me, it's feels much better to let the Entity classes to worry about themselves. But I also understand your concern of the NHibernate performance issue. So, my suggestion is to implement the validation logic in Setters and use field for NHibernate mapping.

Resources