Access static content from area w/o "Areas" in url - asp.net-mvc

I am currently working on a web app with a small web page on the root level and several (more complex) web pages in areas.
All area-based web pages have static content that is independant of each other, so each of them has it's own content folder.
Unfortunately the resulting url's for the static content contains the string "Areas", for example
http://myappurl/Areas/MyArea1/Images/myFile.png
Since Areas are a technical implementation detail and nothing that the user should know (or care about), they do not belong in the url.
How can I fix that?
I don't want to create another root-level directory for each area (would be confusing and error-prone), but I don't really understand how I could modify routing to allow this otherwise.
Help would be appreciated :)

By default, ASP.NET does not handle requests to .png files.
Scott Hanselman has an article that explains how to change this functionality. Link: Back to Basics: Dynamic Image Generation, ASP.NET Controllers, Routing, IHttpHandlers, and runAllManagedModulesForAllRequests.
If you follow the instructions there, then you will be able to gain control of how requests to all png files are routed. So, you get to define routes the same way for the file nested within the area as you do for any other View/JSON/XML. The trick is then to set the appropriate content type and render the image as a filestream.

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.

Integrating webpages and turbogears application

I am working on a Turbo Gears 2 application. The application directs a user through a set of questions. I like the templating system of TG2 (which of course is the idea) so I want to integrate the static web pages with TG2 also. This will allow me to abstract away the headers, sidebars, navbars and footers.
Please note that I am not talking about placing my 'static' files in the public directory of the application. I created a Controller called WebController and I am serving files through that. Of course the instance name of the controller is web so all my pages are accessible at the URL http://mysite/web/page1.html (for example)
Now the question - is it possible to have all pages at the root level be redirected to /web. That way I can eliminate the /web in URLs for HTML pages.
Thanks for reading.
Ok I realize that my question was somewhat vague. After doing some research on my own, I found out that TurboGears does not use routes by default but uses CherryPy dispatching scheme. http://nxsy.org/unscientific-and-biased-comparison-of-django-pylons-and-turbogears was very helpful in understanding some of the high level architecture of TG.
I rely a lot on stackoverflow to solve my problems as I make progress in my application - so, here is hoping someone else can benefit by reading that discussion.

Design Practices - Several Pages with ASP.NET MVC

Is there a specific design practice for MVC type sites that need to have a lot of non-model related pages? I mean, it seems very silly to make a controller action for every single page; Yet at the same time, that seems to be the only way to realistically do it and adhere to standards. Is there any documentation or examples available for things like this?
When I speak of non-model pages, I mean things that are just display; Static information that you might use a standard HTML website layout for. But it has to be intermingled with other parts of the site that do require models and validation/etc.
Create a folder for your static content, and put in an ignore route for those pages. This causes those pages to be passed through directly to IIS for immediate display.
routes.IgnoreRoute("StaticPages/{*path}");
You can also load static HTML content into an existing View. This preserves your ability to work with dynamic content in the same page.
I don't think it sounds silly at all to make an action for every page. That's just how MVC works.
You can ignore some routes, as Robert Harvey suggests, but then you'll have the *.html extension on your static pages but not your internal ones, and you'll be unable to use the Url. and Html. helper methods for linking to MVC actions.
I think you should just go with the flow.
Another alternative was suggested for common static files such as help pages which is based more on a naming convention, but would allow for some flexibility in layout control in the view:
ASP.Net MVC Routing Strategy for Static Content

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

What is the best/cleanest way to implement A-B testing in asp.net mvc?

What is the best and cleanest way to implement A-B testing in asp.net mvc? That is, when we make new changes to an asp.net mvc web site, we want to test the new html/css/js with a certain subset of visitors (defined on cookie, login id, etc) and then analyze some metrics (page response time, number of pages visited, $$$ in sales, etc) afterwards to measure the level of success of the changes.
I am looking for a clean way to implement a way of choosing what view (html/css/js, etc...) to render using asp.net mvc.
Check out FairlyCertain (http://www.fairtutor.com/fairlycertain/) when you get a chance. It's a .NET A/B library that you can pretty much just drop into your project and start writing tests.
Unlike the Javascript libraries from Google and VisualWebsiteOptimizer, everything happens on the server so you don't suffer any performance, user experience or SEO issues. I've been using it in my stuff for a while now and it works quite well.
There is an A/B testing framework specifically for ASP.NET MVC. This is an open source software I wrote myself when, just like you, didn't find a free tool which works nicely with ASP.NET MVC and doesn't require much setup.
Google Content Experiments? It's a Javascript-based solution that doesn't require anything from your backend.
You include Google's Javascript on your page
The script randomly substitutes elements on your page as defined by your A/B test
Google's site shows you a nice breakdown of the results...
If you are using the spark view engine, you could probably do it with a variation of the theme filter (http://sparkviewengine.com/documentation/viewlocations#Extendingfilepatternswithdescriptorfilters). For each new visitor to the site, determine if you want them to see the existing or new version of the site and set a cookie. Wire up a descriptor filter that looks for the presence of the cookie and modify the view location to look in the folder containing the modified views. If an alternative view exists, the Spark engine will automatically render it in place of the "normal" view, otherwise it will render the normal view.
If you are using the normal WFVE, then the simplest way to manage this would be to define a folder under Views where your view alternatives live. When you want to provide an alternative view, you place it in a location that matches its position within the normal Views folder but rooted at the alternatives folder e.g. to provide an alternative to Views/Users/login.aspx place your new view at Views/Alternative/Users/login.aspx.
With a convention in place for locating your alternative views, you can extend the WebFormViewEngine and overload CreatePartialView / CreateView to inspect some aspect of the ControllerContext to determine whether to render the default or overloaded view and alter the path as appropriate e.g. changing .../Views/Users/login.aspx to .../Views/Alternative/Users/login.aspx.
I suggest you use Display Modes to achieve A/B testing.
But Display Modes just support simple problems by default.
If you already implement Display Modes in some other scenario. You can consider DisplayModeMatrix (just google it). It helps you use Display Modes more efficiency.
https://www.nuget.org/packages/DisplayModeMatrix/
Wth Display Modes you can simply delete/rename views after A/B testing to clean up your project.
I think there isn't a ready to use solution for this and you will have to improvise.
Try to override your current functionality in well defined points without breaking it. Explicitly draw a border where your regular code and A-B testing code lives.
Inversion of control principle might help a lot here too (i.e. - controller factory could provide derived controller instead of original one). For views&partialviews - you could change viewengine so it would try to look for 'MyPartialViewAB.ascx' instead of 'MyPartialView.ascx'.
And it might be a good idea to take a look what performance counters are (in case you haven't).

Resources