MVC Area Routing not working for one specific area in my web application....Returning 500.19 with wrong phsyical path - asp.net-mvc-4

I have an asp.net mvc web application with multiple areas.
There are about 15 areas within this application all of these route correctly except for one area.
This area blows up when I go directly to the index page with a 500.19 error.
The routing, controller, and views are essentially very similar for all areas involved.
The one thing that I have noticed is that the error provided shows the incorrect area path (physical path) for the specific view that is being requested. This can be seen in the image provided, but it is showing this as the physical path to the robin index view. :
C:\Projects\mvc\Test\BatmanProject\Index
Whereas it should be showing something like this. :
C:\Projects\mvc\Test\BatmanProject\Areas\Robin\Views\Home\Index
As you can see below it is attempting to find the index view directly in the batmanproject versus looking in the robin area. Whereas all the other areas (Riddler, Joker, etc etc) are finding the index directly in their corresponding area without throwing a 500.19 error.
I know it is not web.config related because all the other areas are working. I have tried numerous things such as. :
wiping out the host config and temp aspnet files
clearing out all the applications in my iis
running aspnet_regiis -r
numerous other fixes
I am just confused as to why it would occur for this specific area and not the others any one else seen an error like this?
***Route having issue
http://localhost/BatmanProject/Robin/Home/Index
***AreaRegistration
public override string AreaName
{
get
{
return "Robin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Robin_default",
"Robin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

Related

Hook up Auth0AccountController in Umbraco 7

Has anyone successfully integrated Auth0 with Umbraco 7 for member (front-end public users, not CMS back-end users) authentication?
I've successfully integrated with owin startup and dealing with signin-auth0 response. However I'm stuck on hooking up the Auth0AccountController to work with Umbraco (I'm getting a 404). Any suggestions?
I've tried adding ~/Auth0Account to the "umbracoReservedPaths" appSetting, but I just get a slightly different looking 404 (not controlled by Umbraco by looks of it).
I've also tried mapping the route in Startup.cs using
RouteTable.Routes.MapRoute(
"Auth0Account",
"Auth0Account/{action}",
new
{
controller = "Auth0Account"
}
);
but that results in a "No route in the route table matches the supplied values" error.
Any ideas?
Mapping the Auth0Account route in Startup.cs was correct:
RouteTable.Routes.MapRoute(
"Auth0Account",
"Auth0Account/{action}",
new
{
controller = "Auth0Account"
}
);
Turns out my problem was with the default redirect RedirectToLocal method in the Auth0AccountController controller. It was doing a
return RedirectToAction("Index", "Home");
which I didn't have a controller hooked up for. I replaced this with an Umbraco compatible redirect instead.
Also, instead of Auth0AccountController inheriting from Controller it might be useful to inherit from Umbraco.Web.Mvc.SurfaceController or Umbraco.Web.Mvc.RenderMvcController to expose useful Umbraco methods to the code.

ImageResizer and Images delivered as byte stream

We have an umbraco MVC website with which we are trying to use ImageResizer. In order to keep uploaded files out of a publicly accessible area, images are stored outside of the webroot and we use a controller to deliver them to browswer (e.g. an image url on a page would be something like <img src="/umbraco/surface/AttachmentSurface/ShowImage/999?" alt="Here there be an image, yarrr!">)
The ShowImage action is something like:
public ActionResult ShowImage(int id)
{
using (DBContext db = new DBContext())
{
Attachment a = db.Attachments.FirstOrDefault(x.ID == id);
if (a != null)
{
byte[] file = System.IO.File.ReadAllBytes(System.IO.Path.Combine(System.Configuration.ConfigurationManager.AppSettings["UploadPath"], a.Path, a.FileName));
return this.File(file, a.MimeType);
}
}
}
If we use the URL API on a publicly accessible image (e.g. <img src="/images/kitty.jpg?width=33&height=33&mode=crop" alt="Here there be kitties, yarrr!">), then everything works as expected.
However, we've tried using the URL API to resize our images delivered by the controller to no avail (e.g. <img src="/umbraco/surface/AttachmentSurface/ShowImage/999?width=33&height=33&mode=crop" alt="Here there be an image, yarrr!">).
Is the only way around this to use the Managed API and resize the image before delivering? I seem to remember the documentation saying something to the effect that it's a bad idea to use it from within an MVC Action...
Thanks for any help.
ImageResizer doesn't operate as middleware, unfortunately, as middleware can't access the right resources in order to do a good job. It controls the request from beginning to end, and tries to integrate smoothly with existing authentication, URL rewrite, and CMS modules. That's why it doesn't work on an MVC action. It wouldn't be able to cache to disk, and it would have a severe performance overhead from double-buffering.
If you're just trying to block access to original files, you could do that in a variety of ways without moving the files outside of the root (UrlAuthorization, AuthorizeRequest event, disabling handlers for that folder, etc).
If you want to control where the images come from, you should implement an IVirtualImageProvider class. ImageResizer does include an IVirtualImageProvider plugin (named VirtualFolder) that can provide access to external/off root files. If your needs are basic, give that a try, and drop the MVC action.

injecting changing view engine list

I'm trying to develop a multi-tenancy project wherein each client can have their own specific view engines.
Specifically I'd like to compile the views to a DLL (using RazorEngine) and have an individual RazorViewEngine for each client but also provide a fallback to the standard RazorViewEngine if no matching views are found, just as the MVC framework does if you have multiple view engines specified.
I have found I can inject view engines using autofac in the Global.asax of my MVC 4 project using:
ViewEngines.Engines.Clear();
var builder = new ContainerBuilder();
builder.RegisterType<WebFormViewEngine>().As<IViewEngine>();
Now I also want to provide tenant specific overrides as mentioned above which I can do with the following code:
var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build());
mtc.ConfigureTenant("Client1", b => b.RegisterType<RazorViewEngine>().As<IViewEngine>());
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
In this example code I just wanted to see if I could set the WebFormsViewEngine as a fallback and then enable the RazorViewEngine for a specific tenant.
Upon loading and browsing to a non-tenant url, mvc will resolve just the WebFormsViewEngine as expected (through calling the DependencyResolver and in turn Autofac), this works as expected however when I then visit a url that would also include the RazorViewEngine no views are found, even though a valid razor view exists.
Conversely if I stop IISExpress or do something to generate an app pool recycle and visit a tenantable url first both view engines are registered.
From what I can tell MVC caches the list of view engines retrieved after the first call to the MultiServiceResolver.
internal IViewEngine[] CombinedItems
{
get
{
IViewEngine[] combinedItems = _combinedItems;
if (combinedItems == null)
{
combinedItems = MultiServiceResolver.GetCombined<IViewEngine>(Items, _dependencyResolver);
_combinedItems = combinedItems;
}
return combinedItems;
}
}
Is there a way to override this caching or another better way to achieve what I'm trying to get here?

How do I set push-state in durandaljs 2.0 the works on refresh?

I'm using durandaljs 2.0. I've installed the durandal starter-kit as suggested and explained here. In the shell I'm returning router.activate({ pushState: true } ); as explained in the relevant documentation (see the bottom of the page).
Happily, the URL is indeed in a 'push state' format, e.g. http://localhost:61285/flickr - the problem is that when I refresh the page I get a 404 error telling me "the resource cannot be found". If I set push-state to false ({pushState: false} above) I get a hashed URL, e.g. http://localhost:61285/#flickr - and now a refresh does work. So, how do I set up a push state mode in durandaljs 2.0 that will work with refresh?
Thanks,
Elior
Maybe to late...but
just change the routes config.
simple as this :
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
When you refresh the page, the browser will make a request to the server with that URL http://localhost:61285/flickr.
What's probably happening is that if you are using ASP.NET MVC, the server is trying to locate a Controller called flickr and it throws an exception because obviously there isn't any resource with that name.
In order to get rid of this exception you should configure the server to serve the same HTML of the APP but for unknown URL's. This can be achieved using IIS URL Rewrite in ASP.NET.
So after setting up properly the server, by requesting an unknown URL it would return the initial view for the app plus whatever you pass in the query string parameters so the router can do its job at client side.
In this blog post you will find more information about how to configure ASP.NET to handle this scenarios. In the article the author uses AngularJS, however it will be the same for Durandal.
RainerAtSpirit and margabit, you're both right, thank you. Here is how I implemented the server side:
First I should note that all the interaction with the server is done via WebApi controllers.
so, for example, if the URL is:
http://localhost:61285/home/category2/subCategory22 (for a localhost), the server tries to look for a controller called 'home' and an action in it called 'category2'. Since there's no such action, I get a 404 error.
What I wanted is that the server WILL call the 'home' controller, but send the rest of the URL as parameters to the client. My solution was to add a hash after the controller's name, so that the URL will look like this: http://localhost:61285/home/#/category2/subCategory22. If this would happen then the client will take care of the hashed part with no 404 error.
For this to happen:
I added the following to 'web.config':
<customErrors mode="On" defaultRedirect="Error">
<error statusCode="404" redirect="Error" />
</customErrors>
Then I create a controller named 'ErrorController' with the following class in it:
public class ErrorController : ApiController
{
[HttpGet, HttpPost, HttpPut, HttpDelete, HttpHead, HttpOptions, AcceptVerbs("PATCH"), AllowAnonymous]
public HttpResponseMessage Handle404()
{
string [] parts = Request.RequestUri.OriginalString.Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries);
string parameters = parts[ 1 ].Replace("aspxerrorpath=","");
var response = Request.CreateResponse(HttpStatusCode.Redirect);
response.Headers.Location = new Uri(parts[0].Replace("Error","") + string.Format("#{0}", parameters));
return response;
}
}
what happens is that when the server get a URL with no relevant action as I mentioned above, it redirects it to this controller in the following format: http://localhost:61285/Error?aspxerrorpath=home/category2/subCategory22
as you can see, I manipulate this to add the hash and remove the unnecessary info: http://localhost:61285/home/#/category2/subCategory22 and the redirect the server to the 'home' controller.
You might wonder why I do all of this - the reason is that Durandal, a wonderful platform, enables me to use push state, but in order for that to happen I have to work-around the server getting a non-hashed URL and pass it to the client despite the fact there's no relevant controller/action; Durandal get's a hashed URL but removes the hash automatically and the user eventually sees a hash-less URL while Durandal provides all the necessary push state functionality.
Elior

How do I get the silverlight view page name and querstring from silverlight code behind?

VS2010 w/Ria Services & SL4.
I already have my SL app loaded in the browser.
User clicks around to different view pages and I would like to store their current location in a list of "recently visited pages".
To do that, I need to store the view page + any existing querystring key/values.
Ex: here is a real page in my sl app:
http://localhost:52878/Default.aspx#/DocSearchShell?CM-Origination
I don't care about anything before the # sign - there are a million ways on google to get the http: // localhost:52878/Default.aspx uri from sl.
What I DO want is the "DocSearchShell?CM-Origination" portion of the querystring - that is what I want to capture and store for the "recently visited pages"
How do I do this from sl4 (.NET 4) code-behind?
Thanks!
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// The answer is this:
// e.Uri.OriginalString;
}
You can access the part of query string after "#" symbol via System.Windows.Browser.HtmlPage.Window.CurrentBookmark.
It works from any part of SL application.