MVC url routes not working after deployment on IIS - asp.net-mvc

I have a MVC app that works just fine on local, but when deployed on IIS all the routes return 404 not found.
My browser shows me in some cases the layout but doesn't bring the data for that view and instead of that returns 404.
I will show you a method that works fine on local but in IIS fails.
[Route("/Customer/CustomerDetails/{id}")]
public async Task<IActionResult> CustomerDetails(int id)
{
ApiResult<eCOM_Backend.Api.Responses.Customer> apiResult = await _customerApiMethods.CustomerDetailsAsync(id);
eCOM_Backend.Api.Responses.Customer customerFromBackend = null;
if (!apiResult.HasException)
{
customerFromBackend = apiResult.Result;
}
else
{
return RedirectToAction("Error", "Error", new { reason = apiResult.Exception });
}
CustomerViewModel customer = customerFromBackend.ToCustomerViewModel();
return View(customer);
}
When I call this method like: xxx/Customer/CustomerDetails/123 i get page not found.
I have tried lots of solutions(modified the appsettings.json, web.config etc.) but nothing worked so far.
Thanks a lot!

Looks like this is dotnet core. Make sure to provide correct physical path when you publish your app to IIS. Like inetpub\wwwroot\YourAppName. In IIS right click on your web app >Manage Website>Advanced Settings and make sure physical path ends on your app folder not yourApp\someOtherFolder

Related

MVC 5 how to work with custom URLs or Url Rewriting

I have a gallery website. That developed in asp.net. Now I want to port it to asp.net MVC5. While doing it I run into an issue without solving it I cant go into further development. So here is the requirements:
a) Every gallery has its own independent folder and has photos in it. the url for the photo galleries will be: localhost/gallery1, localhost/gallery2 and so on.
b) Each gallery has two types of layouts and options the commbo is given bellow:
localhost/gallery1/still/grid
localhost/gallery1/still/slide
localhost/gallery1/gifs/grid
localhost/gallery1/gifs/slide
c) change of [gallery1] to any other name should serve the photos from within the new name folder.
d) we also have a way to configure gallery for each folder by accessing admin
localhost/gallery1/admin
localhost/gallery2/admin
I am new to MVC. And I dont know how to work with that... I just created a brand new MVC5 project using Visual Studio with builtin example. Can anyone help me how to deal with this?
EDIT:
The controller has to be a universal control for anything immediately after localhost/ so in my example urls gallery1 and gallery2 or anything like that will be caught by a universal controller, may be GalleryController.
After the name of the gallery, the next two url segments are going to work in conjugation. I am not sure how to catch them in a universal controller and then segment them out on the basis of what is after still and gifs.
I have found answer to my own question. Here is what i did.
Inside RouteConfig.cs I simply added following mapping:-
routes.MapRoute(
name: "Dynamic",
url: "{name}/{action}/{layout}",
defaults:
new {
controller = "Gallery",
action = "Display" ,
layout = UrlParameter.Optional
});
This is how my GalleryController.cs looks like:
public class GalleryController : Controller
{
// GET: Gallery
public ActionResult Display()
{
return View("Index");
}
public ActionResult Admin()
{
return View();
}
public ActionResult Gifs()
{
if(Request.Url.AbsoluteUri.Contains("gifs/slide"))
return View("GifsSlide");
else
return View("GifsGrid");
}
public ActionResult Still()
{
if (Request.Url.AbsoluteUri.Contains("stil/slide"))
return View("StillSlide");
else
return View("StillGrid");
}
}
Inside my Gallery folder in Views I have following .cshtml structure
Views/Gallrey/gifsgrid.cshtml
Views/Gallrey/gifsslide.cshtml
Views/Gallrey/stillgrid.cshtml
Views/Gallrey/stillslide.cshtml
Views/Gallrey/admin.cshtml
Achievement:
localhost/gallery1/still/grid
localhost/gallery1/still/slide
localhost/gallery1/gifs/grid
localhost/gallery1/gifs/slide
localhost/gallery1/admin

Performance ramifications of serving FilePath rather than View

What are the performance ramifications if any of serving a FilePathResult rather than a view (If we have created server cached copies of a website using a headless browser)
public class HomeController : Controller
{
public ActionResult Index()
{
var url = Request.RawUrl.Replace("/", "_");
var path = System.Configuration.ConfigurationManager.AppSettings["PreloadPath"] + "\\" + url + ".html";
if (System.IO.File.Exists(path))
{
return new FilePathResult(path, "text/html");
}
else
{
return View("Index");
}
}
}
We are having to access the AppSettings every request now, use the File System to check if a file exists, and then serve that html file.
What costs are there compared with just
return View("Index");
Will the file access have any cost on the server? Or am I talking nonsense, and IIS would have to perform some similar action?
Note: Please suggest any other tags if I should add them
Looking at the FilePathResult's source code you can see that in the end it goes down to WriteStreamAsText of HttpResponse. It's obvious that there is no magic call to IIS for example to handle the file directly without any .Net code taking place.
Having said that I still expect this to be somewhat faster than running a view, which possibly needs interpretation and execution.

MVC .NET site inks not pointing correctly to the base URL

I have developed and tested a site on an IIS server at an IP address. Everything was and is working perfectly if I use the IP address in the URL. However for production, the client wanted a friendly domain URL. In other words https://www.IPAddress.com is supposed to point to my default MVC login page at https://www.example.com/department/Account/Login. The client's network team set it all up and most of the links work fine.
However, in some other places the "/department" is not getting appended to the URL, and the link goes to https://www.example.com/Action/Controller (instead of https:www.example.com/department/Action/Controller).
What I discovered so far is that #Html.ActionLinks in Views are pointing correctly.
So this works: #Html.ActionLink("Create a login!", "Register").
It correctly points to the URL https://www.example.com/department/Account/Register.
But this does not (in controller code):
if (await UserManager.IsInRoleAsync(user.Id.ToString(), "Admin"))
{
return RedirectToAction("Dashboard", "Admin"
);
}
if (await UserManager.IsInRoleAsync(user.Id.ToString(), "User"))
{
return RedirectToAction("Dashboard", "User");
}
The code posts incorrectlyto https://www.example.com/Admin/Dashboard, instead of https://www.example.com/department/Admin/Dashboard
Does this have to do with something the network folks have not done. Or is there a place I can set the base URL in my webconfig file?
Thanks in advance,
Sanjeev

Kendo UI Async Upload not working in Internet Explorer

I'm trying to use the Kendo UI Upload (MVC wrapper) in async mode. Things seem to work fine in Chrome, but no such luck in IE (as of now only tested in IE 9). When it initiates the upload, I can see it hitting my action method and the request contains the data I expect, but nothing is actually being saved.
Code samples are below:
_EditForm.cshtml (where the upload is)
#(Html.Kendo().Upload()
.Name(string.Format("upload{0}", "background"))
.Multiple(true)
.Events(evt => evt.Success("refreshBackgroundImages"))
.Messages(msg => msg.DropFilesHere("drag and drop images from your computer here")
.StatusUploaded("Files have been uploaded"))
.Async(a => a.AutoUpload(true)
.SaveField("files")
.Save("UploadImage", "Packages", new { siteId = Model.WebsiteId, type = "background" })))
Controller ActionMethod
[HttpPost]
public ActionResult UploadImage(IEnumerable<HttpPostedFileBase> files, Guid siteId, string type)
{
var site = _websiteService.GetWebsite(siteId);
var path = Path.Combine(_fileSystem.OutletVirtualPath, site.Outlet.AssetBaseFolder);
if (type == "background")
{
path = Path.Combine(path, _backgroundImageFolder);
}
else if (type == "image")
{
path = Path.Combine(path, _foregroundImageFolder);
}
foreach (var file in files)
{
_fileSystem.SaveFile(path, file.FileName, file.InputStream, file.ContentType, true);
}
// Return empty string to signify success
return Content("");
}
Well as another post said, "Welcome to episode 52,245,315 of 'Why Does Internet Explorer suck so badly':
Turns out that when you do file.FileName on an HttpPostedFileBase in Internet Explorer, it thinks you want the whole path of the file on the local machine. It's obviously an IE only thing as Chrome and Firefox seem to have it right.
Make sure to do the following when you only want the actual FileName:
var filename = Path.GetFileName(file.FileName);
The problem is when you actually try to save a file and send back a success response from the server. I don't think your demos are doing any of that. The iframe in ie9 does not receive the response from the server. The browser thinks the response is a download even though it's just a plain text json response. I debugged it down to the fact that the on load event on the iframe never gets fired so the onload handler that needs to handle this response is not doing anything. In all other browsers this is working.
Source: http://www.kendoui.com/forums/kendo-ui-web/upload/async-uploader-and-ie-9-not-working.aspx

On Redirect - Failed to generate a user instance of SQL Server

Hello (this is a long post sorry),
I am writing a application in ASP.NET MVC 2 and I have reached a point where I am receiving this error when I connect remotely to my Server.
Failed to generate a user instance of SQL Server due to failure in retrieving the user's local application data path. Please make sure the user has a local user profile on the computer. The connection will be closed.
I thought I had worked around this problem locally, as I was getting this error in debug when site was redirected to a baseUrl if a subdomain was invalid using this code:
protected override void Initialize(RequestContext requestContext)
{
string[] host = requestContext.HttpContext.Request.Headers["Host"].Split(':');
_siteProvider.Initialise(host, LiveMeet.Properties.Settings.Default["baseUrl"].ToString());
base.Initialize(requestContext);
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Site == null)
{
string[] host = filterContext.HttpContext.Request.Headers["Host"].Split(':');
string newUrl;
if (host.Length == 2)
newUrl = "http://sample.local:" + host[1];
else
newUrl = "http://sample.local";
Response.Redirect(newUrl, true);
}
ViewData["Site"] = Site;
base.OnActionExecuting(filterContext);
}
public Site Site
{
get
{
return _siteProvider.GetCurrentSite();
}
}
The Site object is returned from a Provider named siteProvider, this does two checks, once against a database containing a list of all available subdomains, then if that fails to find a valid subdomain, or valid domain name, searches a memory cache of reserved domains, if that doesn't hit then returns a baseUrl where all invalid domains are redirected.
locally this worked when I added the true to Response.Redirect, assuming a halting of the current execution and restarting the execution on the browser redirect.
What I have found in the stack trace is that the error is thrown on the second attempt to access the database.
#region ISiteProvider Members
public void Initialise(string[] host, string basehost)
{
if (host[0].Contains(basehost))
host = host[0].Split('.');
Site getSite = GetSites().WithDomain(host[0]);
if (getSite == null)
{
sites.TryGetValue(host[0], out getSite);
}
_site = getSite;
}
public Site GetCurrentSite()
{
return _site;
}
public IQueryable<Site> GetSites()
{
return from p in _repository.groupDomains
select new Site
{
Host = p.domainName,
GroupGuid = (Guid)p.groupGuid,
IsSubDomain = p.isSubdomain
};
}
#endregion
The Linq query ^^^ is hit first, with a filter of WithDomain, the error isn't thrown till the WithDomain filter is attempted.
In summary: The error is hit after the page is redirected, so the first iteration is executing as expected (so permissions on the database are correct, user profiles etc) shortly after the redirect when it filters the database query for the possible domain/subdomain of current redirected page, it errors out.
Make sure App Pool is set to NetworkService if under windows 7 and IIS 7.5
I searched long and hard for this one, it was my error all along. It seem that at sometime someone decided to change my applciationpool settings and changed the applicationpool for my application. But for some strange reason it didn't impact me until I tried to use the redirection code.
Before adding the code all databases connected without any issues and data was pulled without error, but afterwords it didn't, so after looking at my appool, I noticed it was not set to networkservice any longer, switched, fixed.
So maybe this question should be, why would database connections work before the new code, but not after while not under networdservice user?

Resources