MVC project - two sites same controllers - c#

I have a dilemma how to organise my new project.
At the moment, I have a magazine style website coded in MVC C# where every page has an own controller with a set of views. Behind controllers, we have a service layer (as a separate project) for accessing to database. Majority of the business logic is in service layer with some bits of the business logic in controllers
We're planning to launch a new website which is going to use a copy of the 1st site database, with 95% the same features as the first website but completely different views/css.
We have a really tight deadline and we want to reuse as much as possible of the existing code and to make both sites super easy to maintain.
As far as I can see we have two options:
To create a new project for the 2nd website, where we will need to re-write all controllers from scratch
To add a new set of views to the existing website and based on a configuration switch to show different views based on the url of the 1st or 2nd site.
1st approach is much cleaner but at also it will generate loads of repeated code and probably a maintenance nightmare.
2nd approach will use the same controllers (with potentially doubled methods for 5% of different functionalities).
Is there 3rd of doing this?
thanks

At the end I decided to implement custom views via DisplayMode
DisplayModeProvider.Instance.Modes.Insert(0, new NewSiteDisplayMode()
{
ContextCondition = context => IshkaDisplayMode.IsNewSite(context.Request)
});
Now if I need a custom view for the new website I just create a copy of the existing view add NewSite into name and put specific HTML inside.
Cheers

I would use approach 2 if the changes to the business logic are minor and if you can keep it compatible.
There is in fact a third approach, which would be to create a source control branch for v2. You can keep maintaining v1 and integrate the changes to v2 when necessary. Over time however, as your sites drift, these integrations are going to become harder. This approach would thus only be suitable if you have a definite cutoff to get rid of v1.
Depending on the changes to the data model you may need to be able to version your data access code also.

James,
You can use software branching, trunk based development.
Your 2nd approach is smart, where you only have to create new views and rest of your website including business logic, server validations will work like charm.
Infact that is the pure essence of MVC development.

Related

How to separate the view and the controller in an ASP.NET application

I have an ASP.NET application that was developed by "programmers". This application contains all things which you should not do:
Hardcoded settings
Copy/paste anywhere (code not re-used)
Make a lot of small SELECT requests to the DB for each row instead of doing JOIN
Model, view and controller in one function
Etc.
Now, my goal is not to throw everything away and start over, but I want to separate different aspects of the MVC of the application. I do not want to start a new MVC project, I would like to evolve the existing solution into something modular.
For the controller, there is no problem, I can create classes that will manage DB connections, send mails etc. On the other hand I do not know how to separate the view and the controller.
The problem that traditional ASP pages myPage.aspx have an associated file myPage.aspx.vb and in this vb file there are both view management part(page elements, like dropdowns) and also the Business part (controller) which is executed on the button click.
I thought about making a call to a myPageControl.vb class that will contain the business part from the file myPage.aspx.vb, which will call the Model (db, mail, other).
(View: myPage.aspx.vb) -> (Control: myPageControl.vb) -> (Model: Db.vb, Mail.vb)
The problem is: how should I do to modify the page content from the controller, for example change a list value or display a text on it. I have to make a call to the View (to the other direction) and pass by parameter the class MyPage (.asp.vb)
I have already tried to find an answer to my question, but I've found only answers taking about MVC projects.
Does anyone have any idea how I should do it?
Seperation of Concerns was one of the main problems with webforms, and one of the advantages of MVC. In my opinion the best you could probably do is seperate the business logic into classes like you are doing now so code could be reused throughout the application, but completely "seperating" everything may require rebuilding the application as an MVC app.
The only answer I've found to this is to have the controller send the "data to bind to" to the page as XML. then all the page has is its page_load of course, and then a method to receive the XML and update itself from it. You can use smart naming structures so that you can do reflection and autobind from the xml to page elements.
Then on an action, have the page generate an xml of all the elements on it and their values, and send that through a "ProcessAction" method that determines the correct controller and calls the right method on the controller.
But as suggested, doing it over as an MVC project probably makes the most sense if that's the pattern you are going for. What I suggested works, but it will be as much or more work than just starting from scratch with MVC. Besides, remember that "support" for web forms is disappearing soon. It's not in (and won't be in) .NetCore, so it's days are numbered.

multi tenant or multi instance application on intranet

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.

Sharing / Extending Controllers in large ASP.net MVC application

I'm developing a fairly large application.
It's basically an eCommerce app- with other "features" like Forums etc...
The "back office" app will be called "Wokingham"
What I currently have is something like this:
(we have a naming convention bases on names of trees)
MyCompany.Honeysuckle
Project that contains the Model and Data Access (IRepository etc..) for forums
MyCompany.Willow
Models and data access for Products, product search etc...
MyCompany.Poplar
Models / data access / services etc.. for Orders
MyCompany.Juniper
Customers
All the above are class libraries, that compile into a common /bin/ dir
Wokingham (the admin backend system, mentioned above) will share some functionality with the "public" web app-
For example- in Forums (MyCompany.Honeysuckle) - the public app will have the ability to add a new Question.
This functionality is also available in Wokingham.
My question is when it comes to Controllers of the MVC applications.
There will be (at least) 2 ASP.NET MVC Applications-
A separate one for "Wokingham"
Should I have a MyCompany.Honeysuckle.Controllers project? That both the public UI project and Wokingham share.?
Or-
Should there be the MyCompany.Honeysuckle.Controllers mentioned above, but then the .Wokingham project extends the controllers to perform additional required functionality?
I would separate the two controllers, one for front-end operations and one for admin side. The tricky question is where to put the shared operations.
The short way: can you just redirect/open new window if an admin user wants to create a new forum post? This would save you lot of time, and is common practice.
The long way: if having two pages doing the same thing is necessary, then I would go with separate controller operations and views, but shared CRUD services (model layer). The work is mainly to create the different view.
Generally speaking, you want to keep controller operations as simple as possible, as they are just end-point to web requests. And going through the trouble to abstract similarities between two slightly different controller operations is overkill.
Edit: removed irrelevant suggestions.

How to make one ASP.NET MVC site "derive" from another

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.

Grouping Views, Controllers, Models in MVC

maybe i am wrong but i seriously i don't like the current structure of MVC application, and i think on big projects it will cause trouble to maintain.
so is there a way to group related Controllers,Views, Models together, like if i have gallery Module i want all it's Controllers, Views, Models to be grouped under Gallery Folder.
Areas sound like what you are looking for. This will let you group controllers/views/etc. Unless I misunderstood the question?
Phil Haack discussed this here, it's the same issue I've faced and have yet to overcome correctly.
From the sound of it you're moving against the basic principals of MVC, that being the separation of Model, View and Controller rather than your desire to split at 90 degrees to that by using modules.
I'm not entirely sure what benefit you would get from splitting it in to modules any way since I would expect you to have one GalleryController. Where you are likely to have the most 'entities' needing grouping is with the views, possibly one or more for each GalleryController action, but they are in their own folder which gives the sort of functionality you are looking for anyway.
Finally there are the models. Obviously I don't know your project so I don't know how it is laid out, but the Models do not usually exist for the use of one Controller (or module in your case). For example - I have Models for Users, Companies, Vehicles, etc, etc. These models are a shared representation of my data structure and have nothing to do with modules as a user may see it looking at a web page. I can't split them in to modules because the whole point is that they are shared by the entire application.
So...in reality it is the Views which can get a bit messy, but they are already split in to folders based on their Controller. Having said that you can move them around a bit if that suits your needs better. For the rest of it there is no need, either because you shouldn't if you want to use 'proper' MVC (i.e. modular Models) or there's no need (i.e. only one Controller). And if your controller gets too big just create a separate module for any functionality in that you want to split out. I reckon that's as modular as you should ever need to get.
I found a relatively simple solution that uses IIS configuration to simulate areas. No extensions to the existing MVC framework are needed.
Create a new MVC project under your solution for each area you want in your site (ex. Root, Blog, Forum, App1, App2). If you need any common supporting code or a common model, put it in a seperate dll project that the MVC projects depend on.
In IIS, configure the site root to point at the root project directory. Create web applications under the site root that point to each of the sub-area project directories.
When configuring the route maps for each sub area, don't include the name of the application in the route. IIS seems to take care of this for you. (ex. "ShowPost/{postname}", not "/Blog/ShowPost/{postname}")
The benefit is that you can change the name of the web applications independent of the routing system, and each application believes it is running with the whole server to itself.

Categories