Using MVC 3 to dynamically create Site.css on IIS 6. Works in dev, prod fails. Why? - css

I am using an MVC controller/action to dynamically create the site.css in my MVC 3 site. The way it works is I map a route to Site.css like so:
routes.MapRoute("CSS", "Content/Site.css", new { controller = "CSS", action = "Index" });
Then in my CSSController I have the following code:
public ActionResult Index() {
string path = Request.PhysicalPath.Replace("Site.css","SiteStyles.css");
byte[] data = null;
try {
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) {
data = ProcessCSS(fs);
}
} catch (Exception e) {
Logger.Write(new LogEntry(e.Message, "Error", 99, 1001, System.Diagnostics.TraceEventType.Error, "CSS Error", null));
throw e;
}
return File(data, "text/css","Site.css");
}
What's going on in the ProcessCSS method is it's going through SiteStyles.css and performing a find/replace on some constants I have defined, so that I can have a set of colors defined at the top as named constants, then anywhere I need that color in the site I just use the named constant. That way I can change the color once, and it propagates to all of the appropriate places in the stylesheet without me having to go touch 5-6 different places.
The above code works great debugging in my local environment and on the dev server, which is Windows Server 2003 running IIS6. However, when I deploy it to a production server that is also Windows Server 2003 running IIS6 the css is not being loaded and when I try to browse to Site.css (which should be getting mapped via my route) I get a 404 not found error. If I go to my dev server and get the output for Site.css and create a physical Site.css file on the production server, it works.
Any idea why this is failing on the production server?
I added some logging to my CSSControler to log where it is looking for SiteStyles.css and the log simply isn't being generated on the production server, which tells me the server is ignoring the mapped route entirely and not executing the code in the Controller.
Any suggestions on where to start are appreciated.

Sounds to me like you should double-check your IIS configuration on the production server to make sure that the necessary mappings are applied.
Are you using a wildcard (star) mapping in IIS on your development server, or did you define a mapping for the .css extension? You may need to verify that the production server has the same mapping.

Try to add write rights to the folder your css is located in to the user that your pool is run under.

Related

Keep URL extensions

I know that removing URL extensions is the new model for website programming. Unfortunately, my site is hosted on a hybrid server configuration. The call to my site goes into an Apache server that recognizes that my call is for a .aspx page, and passes the call along to an IIS server to complete the call. This complicates my website at this point because I am coding in Visual Studio 2015, and it models after the new rules of removing the extensions, and the call is never passed along to the IIS server.
I am not a big HTML guy, and I cannot find anything to place in web.config or my global.asax file for code to tell the system to overwrite the rule of removing the extension, and to keep my extensions. I have seen several posts here to remove the extensions, but nothing to keep them.
Basically, when I call www.mysite.com/Default.aspx, the current config removes the .aspx extension, and the call is for www.mysite.com/Default. I want to KEEP the .aspx extension on the call to the site so that it passes through the Apache server and to the IIS server. Any help would be greatly appreciated.
Have a look in your App_Start directory for a class called RouteConfig.cs and disable AutoRedirectMode using this line of code
settings.AutoRedirectMode = RedirectMode.Off;
This is what automatically removes extensions from your web pages.
Full example below...
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Off;
routes.EnableFriendlyUrls(settings);
}
}

Dynamically created css not working on Azure website

I am working on Web Form project to deploy on production. In this project, dynamic folder is created on fly and put the new css style as per data configuration from database. This was handled by Handlers in web form. Application works locally without any error. But when I publish on production it does not find the dynamic created css file path. Its not physical exists it creates on fly. So it fails to download css and it missing all images and styles. Another team had developed this application and we are moving this from FireHost to Azure site. It was working on Firehost but no any luck on Azure site yet. I tried to remove manifest file in production by adding remove attributes .manifest in web.config. But no any luck yet. I appreciate your help Thanks
I am getting 404 errors,
Failed to load resource: the server responded with a status of 404 (Not Found)
I have the style css inject this way in site.master page.
<link href="/Styles/Dynamic/CompanySite.css" rel="stylesheet" type="text/css" />
It did not mentioned handlers in web.config. There is separate handlers folders and pages. In pages code behind file look like this in page load method.
StringBuilder sb = new StringBuilder(File.ReadAllText(Server.MapPath("~/Styles/CompanyStyles.css")));
string sPrimaryColor = "#B1D74C";
string sSecondaryColor = "#8BBB29";
string sPrimaryTextColor = "#000";
string sSecondaryTextColor = "#000";
string sBannerId = "1";
try
{
var settings = new CompanySettingDataLogic().Retrieve();
if (settings != null)
{
sPrimaryColor = settings.primary_color_txt;
sSecondaryColor = settings.secondary_color_txt;
sPrimaryTextColor = settings.primary_text_color_txt;
sSecondaryTextColor = settings.secondary_text_color_txt;
}
var BannerId = new CompanyThemeDataLogic().GetBannerId();
if (BannerId.HasValue)
sBannerId = BannerId.Value.ToString();
}
catch (Exception Ex)
{
new Data.Config.ErrorLogDataLogic().LogException(Ex);
}
sb.Replace("#PRIMARY#", sPrimaryColor);
sb.Replace("#SECONDARY#", sSecondaryColor);
sb.Replace("#PRIMARYTEXTCOLOR#", sPrimaryTextColor);
sb.Replace("#SECONDARYTEXTCOLOR#", sSecondaryTextColor);
sb.Replace("#BANNERIMAGEID#", sBannerId);
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Cache.SetCacheability(HttpCacheability.Private);
Response.Cache.SetExpires(DateTime.Now.AddDays(2));
Response.ContentType = "text/css";
Response.Write(sb.ToString());
Its not physical exists it creates on fly. So it fails to download css
and it missing all images and styles.
Where have you stored the files after the folder being created? Do you store them in website Azure vm disk? Please note
the VM disk storage is not persistent
if you have >= 2 instances on Azure to host the web app, and then you just created the css/images files on 1 instance (VM), later your end user may hit the other instance that has no such files.
so please store your files in Azure storage - blob and use its url in your project to connect to css/image files

Programmatically retrieving IIS log file location in an ASP.NET application

I'm trying to determine the location of the IIS log file location of my ASP.NET application. I tried WMI, but wasn't able to find it. Any suggestions?
Note: I want to be able to retrieve the location programmatically; inside my application for further use.
Edit: Here's my code: This works but does not give me the actual physical directory location of the logs. So this is basically useless.
ManagementPath p2=new ManagementPath("IIsLogModule.Name='logging/Microsoft IIS Log File Format'");
ManagementObject log = new ManagementObject(scope, p2, objectGet);
log.Get();
logPath.Text = log["__PATH"].ToString();
On IIS7 you could use Microsoft.Web.Administration assembly, Site class has a property named LogFile, you can get various info about log file for site, for example log file directory can be obtained with this code:
ServerManager manager = new ServerManager();
Site mySite = manager.Sites["SiteName"];
Response.Write("Log file directory : " + mySite.LogFile.Directory + "\\W3svc" + mySite.Id.ToString());
I don't like very much that hardcoded part with directory prefix for site, but didn't find any other better way
You should able to use ADSI (or WMI) to do that - browse IIS metabase and look for 'LogFileDirectory' property for the web site node. For example,
var root = new DirectoryEntry(#"IIS://localhost/W3SVC");
var sites = root.Children;
foreach(DirectoryEntry site in sites) {
var name = site.Properties["ServerComment"][0];
var logFile = site.Properties["LogFileDirectory"][0];
}
Disclaimer: Untested code
See this powershell example using similar idea.

iis7 / asp.net not showing modification of a file

I have currently moved my asp.net 4.0 web application onto IIS7 (windows 2008 server). I used a test folder to hold files from a directory on the localhost machine, however; when I moved the aspx file over and changed the code(on the server), the application keeps throwing this error
Could not find a part of the path 'C:\Users\***\Desktop\TestFolder\'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\****\Desktop\TestFolder\'.
I only have two functions that deal with directories and neither function points to that test directory anymore.
private int checkForFileNumbers()
{
string url = "c:/***/realfolder";
DirectoryInfo directory = new DirectoryInfo(url);
return directory.GetFiles().Length;
}
private void checkForFiles()
{
string url = "c:/***/realfolder";
DirectoryInfo dir = new DirectoryInfo(url);
foreach (FileInfo files in dir.GetFiles())
{
FileDropDownList.Items.Add(files.Name);
}
}
I have tried commenting everything in this aspx file out, only to find that this problem still occurs. I performed the issrestart from the cmd line and nothing changed. Any help would be appreciated.
This is a deployment problem. Your error message is clearly out of sync with your current code. The actual code that is being run from IIS must be coming from an out-of-date binary. As a starting point, I would delete all DLLs in your bin directory on the server and redeploy fresh DLLs. The may also require you to refresh your aspx files depending on what kind of project type you're using.
Once you get this sorted out, I would take another look at how you are deploying updates to your site. Visual Studio and IIS 7 offer some neat deployment options if you want to go that way. Also, you could deploy via Git or SVN. But deployment by manual replacing single files is going to lead you to the type of trouble you are currently experiencing.
If realFolder directory exists under root of your web-app or itself is root then use Server.MapPath method to get real path of virtual folder.
For instance,
String rootPath=Server.MapPath("~"); // It will return real path of current web-app's root.
//OR - In case if want use Server property from separate code file.
String rootPath=HttpContext.Current.Server.MapPath("~/testFolder");
Since you're not referencing the path in your code, it's probably either in one of your config files, HttpModules, Global.asax, or perhaps a DLL.
What other components are you using?
Before moving it to a server, have you tried running the site under IIS on your local machine? Maybe attach a debugger and see where the error is thrown?
Oh, FWIW, the IIS AppPool identity will need to have read permission for your C:/***/whatever folder.

Configure IIS7 to server static content through ASP.NET Runtime

I searched high an low and still cannot find a definite answer.
How do I configure IIS 7.0 or a Web Application in IIS so that ASP.NET Runtime will handle all requests -- including ones to static files like *.js, *.gif, etc?
What I'm trying to do is as follows.
We have kind of SaaSy site, which we can "brand" for every customer. "Branding" means developing a custom master page and using a bunch of *.css and other images.
Quite naturally, I'm using VirtualPathProvider, which operates like this:
public override System.Web.Hosting.VirtualFile GetFile(string virtualPath)
{
if(PhysicalFileExists(virtualPath))
{
var virtualFile = base.GetFile(virtualPath);
return virtualFile;
}
if(VirtualFileExists(virtualPath))
{
var brandedVirtualPath = GetBrandedVirtualPath(virtualPath);
var absolutePath = HttpContext.Current.Server.MapPath(brandedVirtualPath);
Trace.WriteLine(string.Format("Serving '{0}' from '{1}'",
brandedVirtualPath, absolutePath), "BrandingAwareVirtualPathProvider");
var virtualFile = new VirtualFile(brandedVirtualPath, absolutePath);
return virtualFile;
}
return null;
}
The basic idea is as follows: we have a branding folder inside our webapp, which in turn contains folders for each "brand", with "brand" being equal to host name. That is, requests to http://foo.example.com/ should use static files from branding/foo_example_com, whereas http://bar.example.com/ should use content from branding/bar_example_com.
Now what I want IIS to do is to forward all requests to static files to StaticFileHandler, which would then use this whole "infrastructure" and serve correct files. However, try as I might, I cannot configure IIS to do this.
II7 already does that if the application pool's Managed Pipeline Mode is set to Integrated which is the default. In Integrated mode, ASP.NET handles all requests including those for static objects.
If you have to leave your application pool in Classic Mode then you need to use the same techniques you would use in IIS 6 to explicitly create handlers for the various static extensions.
Additional Information Based on Comments: I think your missing piece is creating an HttpHandler to handle the other extensions (.js, .css, etc.). Without this, then ASP.NET will use the default handling for these types of files. You would create a reference to you handler in your web.config. This article is an example of creating an HttpHandler for static files.
Kudos to everyone, but the problem was in totally different space.
VirtualPathProvider cannot be used in a pre-compiled web site. I'm furious.

Resources