ASP.NET MVC Theming Best Practice? - asp.net-mvc

It has now become a requirement that my existing project requires a different 'theme' for different clients. I have never had to do this on an ASP.NET MVC project and it doesn't seem like ASP.NET Theming and MVC go together very well.
I would say that 75% of the CSS will remain the same with the rest being changeable. It wouldn't have to be able to switch on-the-fly as they will be deployed as separate web sites (probably on different servers).
Just wondering if there was a preferred method for doing this sort of thing? I was thinking of just having a base CSS with separate 'client-specific' ones with overriding rules. The client css name could then be be set in the web.config and brought through to the master page for declaration.
Am I on the right track there?

We do this, with a similar approach as the one you described. Base CSS is always loaded, and CSS overrides are applied depending on the client.
The difference is that we don't use an appSetting, though you could. All of our clients are on the same server, so we manage it using a cookie. When a user signs in, we take the part after the # symbol in their email address and set a cookie corresponding to the client ID. Our CSS overrides are in a folder with the same name as the client ID.
We then have a child action that renders the additional CSS overrides in the head section, based on the cookie value.

Related

Front end page urls

I have an umbraco installation.
I published a content named "Account" and umbraco gave it this url /account.
Fair.
Then I published a content named "Register" under content Account (I allowed Account Doc Type to have Register Doc Type as child).
I would expect the url of the new content to be /account/register, but umbrace gave it /register.
Why is this happening? What's the point of allowing child content types, and building a content tree, if the urls are all from root? As a newbie to umbraco, I consider it a logic flaw. For a CMS that claims to be friendly, that's not friendly at all. I'm a developer but I can't waste half of my day looking for umbraco answers and tutorials online. A friendly CMS should be self explicatory while being used, and should take care of all common assumptions a newbie may have.
How can I make the Account->Register content node to appear in /account/register url?
I think what you're seeing is a side-effect of a feature in Umbraco that is supposed to support the pattern most develops use when creating an Umbraco website.
The best practice when building Umbraco websites is to create a "Website/Root/Site" document type and place this in the root of your hierarchical content structure. Beneath this document type you place each of your pages as direct children. This allows you to set hostnames and culture on your site as well as it allows you to keep your entire site in one "bundle", and it also allows you to do multiple subsites within the same Umbraco website. It is pretty common practice to structure your website this way.
However - as you expect - this would give your URLs such as domain.com/website/account/register due to Website now being an actual content node in Umbraco. As this is really not something anyone would want - Umbraco has a built-in feature allowing the top level node to be hidden from the URL path. This results in your URLs being domain.com/account/register in this case.
If you however consider your site - this feature results in your register page getting the URL: /register since the /account part is a top level node that will be ignored when generating URLs.
This behavior is triggered by the setting umbracoHideTopLevelNodeFromPath which can be found in web.config of your site (true by default).
I would however recommend that you do not change this setting and instead add in the root node for your site as it will make things easier for you to manage in the future - it is also the best practice way to structure a site.
This should result in URLs being generated the way you are expecting them to be. Child nodes will have URLs that reflect their name and location in the content tree.

How to add an mvc page to umbraco

I have Umbraco 7.5 and I need to know how to create normal MVC pages for adding new data to my site.
Lets say I have a Doctype "Node" in back-office. I want to let some people be able to add/edit some nodes without going through back-office. How can I do it?
I've tried to create add my view and controller (the MVC way), but apparently Umbraco hijacks all routing and my controller won't hit at all.
I've googled the matter (which is hard since I am not looking for Umbraco forms :| )and I've found this. But I prefer not to add my form as a part of other page. I mean, does it make sense to create a page in back office from type "something" and then on its template I do my add/edit form of another type? Seems strange, right?
I appreciate any ideas/ solution to this matter
You have a couple of options here. You can create a physical page for the editor to sit on, and add the editor as a SurfaceController action (basically an MVC Partial with Postback, that is still part of the Umbraco pipeline). Your form can then use the Content Service API to update the details. The advantage of this method is your code will have access to all of the Umbraco methods and templating out of the box. You could also use WebAPI controllers for the form if you want to do it all client side with JS requests.
You could also use route hijacking: https://our.umbraco.org/documentation/reference/routing/custom-controllers this allows you to have your own custom controllers for Umbraco routes, rather than using the default Umbraco ones. This is a bit more work to set up.
Finally, you can also tell Umbraco to ignore certain paths entirely, and you could run your controllers on those paths. The disadvantage here is that as the routes are being ignored by Umbraco, you don't automatically have access to all the useful Umbraco templating etc.
I've used the first method recently, and it works fine. The only caveat is that allowing users to edit nodes will fill up the version table quite quickly if a lot of users are editing a lot of nodes (every time a node is saved, a version is created). If you're going down this route, you may want to investigate something like Unversion: https://our.umbraco.org/projects/website-utilities/unversion/ which helps to keep old versions more manageable in situations like this.

Hiding view and controller name completely in mvc

Is there any way to hide the controller and action name completely in MVC.
(eg) localhost:81 should always remain same even on clicking any of the action in controller.
i.e., localhost:81/Controller/Action should not happen.
For what it's worth, you don't have to use the controller and action name in the URL. That's just the default. You can always define your own custom routes and make any URL you want hit any controller action you want. This is even easier if you use attribute routing, available in MVC5 or via the Nuget package, AttributeRouting, in lesser versions. This allows you to customize the URL for each action explicitly right on the action definition, which again can be any URL you want.
However, if you're truly looking to have just your domain as the only URL period, then #HadiHassan is correct in suggesting a SPA (single page application) architecture. There's many ways to go about this, so you'll need to just do some research to determine which set of tooling meets your needs best. At one point there was a project template for an SPA app in Visual Studio, it inexplicably disappeared for a time, and I believe it has now returned in the latest web tooling for Visual Studio. However, it's not hard to start from scratch.
You'll most likely want two projects, a Web API and a basic website project. The Web API is to provide your backend connectivity and is where you'll end up connecting to your databases and such, with something like Breeze to provide the connectivity on the client-side (your website project). There's alternatives here though, as you can also easily opt for a backend like a Node.js, which then wouldn't even require ASP.NET at all.
Since a SPA pretty much moves the entire application over to the client-side, you'll want to lean on a robust full-stack JS library. Angular.js is a popular choice, and has support for all the stuff like controllers, routing, etc. that you lose from a server-side MVC application.

ASP.NET MVC website where users can add/remove pages

I'm developing a website for a client, in which they want to be able to manage content and add/remove pages.
At the same time, some pages on the site will be interactive and provide custom reports for logged-in customers.
I've started developing the site in ASP.NET MVC, because I wanted full control over rendering.
However, I'm finding it difficult to conceptually model the site.
If users can add/remove pages, then how can there be a direct mapping of URLs to controllers?
I could do a single 'Page' controller and pass it a content ID, but that would mean that all the code in the site would sit under 1 class file.
I could make the custom/interactive pages sit under different controllers, but then, how will the customer be able to manage them?
I'm really lost with the usability angle of this as well. If I'm building custom interactive pages, how can the client add/remove them anyway? Won't that be modifying the structure of the application itself?
I'm having some problems understanding exactly what you're trying to get at with and what your problem is:
I could do a single 'Page' controller
and pass it a content ID, but that
would mean that all the code in the
site would sit under 1 class file.
I could make the custom/interactive
pages sit under different controllers,
but then, how will the customer be
able to manage them?
What's wrong with "a single class file"? Is your problem from a semantic perspective (ie, you don't want all URLs to begin with /pages)? Or just code management?
Assuming you're serving from a database, I would do the following:
Have a CMSController that accepts requests. It either a) checks the ID (maybe disregarding a stub), or b) takes the stub and looks it up in the db.
Return the content.
That way requests to /CMS/Page/4384 would be served up as you wish. You would then extend this in several ways. Put in a default action, so /CMS/4384 serves up the page. Then add a stub (/CMS/4384/Page-Title-Or-Whatever-Text). Set up additional routes such as /aboutus/ and /product_info/ to all point at your CMSController. Or just have a catchall point to the CMSController.
Also, the controller could open up an html file on the filesystem and serve that.
Does that help at all?
James

ASP.NET MVC using IIS6: Block access to single view (register)

We are using MVC on IIS6. Our site is currently being opened up, but we need to restrict access to the register part of the site, but allow those who can register (i.e. from within our offices) still to sign in and use the site fully.
So inside office can access register and all other site.
Outside office cannot access register and but can access all other site.
Initially, we put file restrictions for the IPs of our offices on the register.aspx file in the views\accounts folder. We were pretty sure this was working, but today, we discover it isn't! Which thinking about it actually makes sense!
So is this possible?
We need to have the other aspx pages in the views\accounts folder usable as views whilst only blocking the register view.
Hope this makes sense!
Neil
Urls defined with ASP.NET MVC are configurable and not based on the folder or file where view page resides.
This means that you cannot use IIS to configure the access for this view pages.
You can filter access to the controllers (and so indirectly the view pages that are called by the view pages). This is done with Action Filtering. On how to create a custom action filter see this page.
So yes, it is possible to limit access to certain pages depending on the ip-address.
I have come across this kind of situation before, but the problem was solved by the way we write applications.
Whenever we've had an application with "some information displayed" and "a way to administer the data" we've always created separate UI projects over the top of the business logic. This isn't just to help with maintainability, it also means that the public bit can be deployed on a public website, while the admin bit can be accessed over the network - so there is no external access at all.
In your example, extracting out the two logical elements would mean that you can deploy two separate web projects with different access rules in IIS.
Another option would be to check the IP address in the executed code for the restricted page - IP addresses can be spoofed, so it's not a completely secure solution.

Resources