MvcRoutingShim plugin has no effect - asp.net-mvc

I'm using the ImageResizer module in an ASP.NET MVC 4 project, along with the plugins SqlReader and MvcRoutingShim.
When I try to access the URL ~/databaseimages/123.jpg (for example), I just get the standard error 404 - The resource cannot be found.
My expectation was that ImageResizer would handle that request and try to read the image from the database, but it doesn't even try to connect (I used SQL Profiler to verify this).
What can be wrong?
This is the output of /resizer.debug:
Image resizer diagnostic sheet 26-06-2012 20:42:57
1 Issues detected:
(Warning): To potentially see additional errors here, perform an image resize request.
You are using paid bundles: Cloud Bundle, Performance Bundle
Registered plugins:
ImageResizer.Plugins.Basic.DefaultEncoder
ImageResizer.Plugins.Basic.NoCache
ImageResizer.Plugins.Basic.ClientCache
ImageResizer.Plugins.Basic.Diagnostic
ImageResizer.Plugins.Basic.SizeLimiting
ImageResizer.Plugins.MvcRoutingShim.MvcRoutingShimPlugin
ImageResizer.Plugins.SqlReader.SqlReaderPlugin
ImageResizer.Plugins.DiskCache.DiskCache
Configuration:
<resizer>
<plugins>
<add name="MvcRoutingShim" />
<add name="SqlReader" prefix="~/databaseimages/" connectionString="database" idType="UniqueIdentifier" blobQuery="SELECT Content FROM Images WHERE ImageID=#id" modifiedQuery="Select ModifiedDate, CreatedDate From Images WHERE ImageID=#id" existsQuery="Select COUNT(ImageID) From Images WHERE ImageID=#id" requireImageExtension="false" cacheUnmodifiedFiles="true" extensionPartOfId="false" vpp="true" untrustedData="false" />
<add name="DiskCache" />
</plugins>
</resizer>
(...)

In your Web.config file, you declared that image IDs are all GUIDs: idType="UniqueIdentifier", yet used a integer in the url: localhost:50272/databaseimages/123.jpg.
<add name="SqlReader" prefix="~/databaseimages/" connectionString="database"
idType="UniqueIdentifier" requireImageExtension="false"
cacheUnmodifiedFiles="true" extensionPartOfId="false"
vpp="true" untrustedData="false" />
If you're not specifying a GUID in the URL, the request will be ignored. Change idType to a different data type, like Int, or use the correct data type in the URL.
Source: http://imageresizing.net/plugins/sqlreader

Related

Specify directory for Serilog rolling file path

Consider this app.config appSetting entry:
<add key="serilog:write-to:RollingFile.pathFormat"
value="ServerServiceApp-{Date}.log" />
This is done at app startup:
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.Enrich.WithThreadId()
.CreateLogger();
This is in a Windows service app. The log file ends up here:
C:\Windows\SysWOW64
Clearly, we’d rather have the log file end up in the same directory that houses this service’s .exe (customers don’t want us writing stuff to SysWOW64). But how?
We need the ReadFrom.AppSettings in there so that the customer can supply serilog settings in the app.config, as necessary.
Is there some way to change the directory used for the log file after the ReadFrom.AppSettings has been done?
Would be awesome if we could say something like:
<add key="serilog:write-to:RollingFile.pathFormat"
value="{ApDomainBaseDirectory}\ServerServiceApp-{Date}.log" />
(And where is {Date}, which can be put in the file path, documented?)
Just put this before the creation of LoggerConfiguration:
Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
Then File.path will be constructed based on the project root path.
The best place for services to write their logs is %PROGRAMDATA% which, by default, is in C:\ProgramData\.
Try:
<add key="serilog:write-to:RollingFile.pathFormat"
value="%PROGRAMDATA%\ServerService\Logs\log-{Date}.txt" />
(Program Files is usually considered to be read-only, and writing stuff here will lead to oddities being left behind unexpectedly during uninstall.)

AzureReader2 with ImageResizer prefix issue

We are using AzureReader2 plugin to read the blob urls and ImageResizer plugin to re-size images on fly.
Our container name is - img
AzureReader2 prefix name is also - img
<add name="AzureReader2" prefix="~/img/" connectionString="DefaultEndpointsProtocol=https;AccountName=my;AccountKey=my endpoint="http://<account>.blob.core.windows.net/" />
So, the image url is looking like below:
http://.blob.core.windows.net/img/img/1GKS2EEF2BR171185/f81c8448-47cb-4448-b1d3-d59a07394bb4.jpg?w=500
img is repeated twice.
Is there any way to handle this?
Can we use empty prefix with ImageResizer?
Any advise is helpful.
Based on the example URL you've provided, I think you are misunderstanding the process. The cloud architecture page can be helpful here.
Your image URL should not be http://myaccount.blob.core.windows.net/img/img/1GKS2EEF2BR171185/f81c8448-47cb-4448-b1d3-d59a07394bb4.jpg?w=500
Without a CDN, it should be in the form http://myserverwithimageresizer.com/img/img/f81c8448-47cb-4448-b1d3-d59a07394bb4.jpg?w=500
Azure's Blob store doesn't know what to do with ?w=500. Your URLs in your HTML pages should never point to blob.core.windows.net; they should point to your server - or, a CDN that points to your server (not the blobstore!).
This question is old but nonetheless as Nathanael's answer says the image URL should be:
http://myserverwithimageresizer.com/img/img/f81c8448-47cb-4448-b1d3-d59a07394bb4.jpg?w=500
Or for example if you are running locally :
http://localhost:<PORT>/img/img/f81c8448-47cb-4448-b1d3-d59a07394bb4.jpg?width=200
To use image resizer you should point to your website then set the reference to blob storage in your web.config file. If it directly access blob storage the image won't have a chance to be resized.
To set the prefix to nothing in web config put the following:
<add name="AzureReader2" prefix="~/" connectionString="DefaultEndpointsProtocol=https;AccountName=my;AccountKey=my endpoint="http://<account>.blob.core.windows.net/" />
By default the prefix is "~/azure" to set it to nothing it should be "~/"
This should make it so if you navigate to
http://myserverwithimageresizer.com/img/f81c8448-47cb-4448-b1d3-d59a07394bb4.jpg?w=500 that your image is retrieved from blob storage and resized.

URL Rewrite 2.0 not excluding subfolder

Could someone please help me to solve my problem?
I'm using ASPX files on IIS 7.5 and URL-Rewrite 2.0 to get SSL in any access condition:
www.somedomain.com -> https://www.somedomain.com
www.somedomain.com/mypage.aspx -> https://www.somedomain.com/mypage.aspx
It's functioning perfectly. BUT, since the page loads/plays some MP3/OGG files, I had noticed that:
1- if the page is executed in SSL, the MP3 does not play in some devices (Androids/iPhone/iPad mobile devices);
2- if the page is executed WITHOUT SSL, it occurrs normally, 100%.
So, I had tried to filter the MP3/OGG files (and also, PNG/JPG images) in URL-REWRITE to avoid their access under SSL.
My filter is:
<add input="{REQUEST_URI}" pattern="(png|jpg|mp3|ogg)" negate="true" />
<add input="{HTTPS}" pattern="^OFF$" />
I had tried a lot of filter settings on these files, as {REQUEST_URI}, {URL}, {UNENCODED_URL} and I see that all of them are ineffective to avoid these files under SSL. I see this using MICROSOFT NETWORK MONITOR, that shows all files being loaded in port 443 (HTTPS). Another characteristic is the fact of I never see the original filenames there (the MP3 files and images). It seems everything is under SSL settings. Another one is the fact of the MP3 does not play in SSL access and the images delay some seconds to load.
I CANNOT utilize the whole domain/folder name (like www.mydomain.com/songs/music.MP3) since I'm using JPLAYER 2.0 and I cannot set this library with the entire MP3 address (the song does not play!), but just the subfolder where they remain, like below (see mp3 and ogg tags):
$("#jquery_jplayer_1").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3:"audio/" + theSongs[0] + ".mp3",
ogg:"audio/" + theSongs[0] + ".ogg"
});
},
play: function () { // To avoid both jPlayers playing together.
$(this).jPlayer("pauseOthers");
},
swfPath: "Scripts/jPlayer/",
supplied: "mp3, ogg",
volume: 0.25,
cssSelectorAncestor: "#jp_container_1",
wmode: "window"
});
How to avoid this kind of behavior? I wouldn't like to put these files (MP3, OGG, JPG, PNG) in another domain to avoid URL-REWRITE to catch them. I need them in the same main project and within one of its subfolder (audio and images folders).
How to create an inbound rule to REALLY discard completely these files?
Note: if I utilize as a rule something like
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
it doesn't play (or loads) too.
I would appreciate a lot your efforts to help me in solving that problem.
Kind regards,
David

Autoversioning CSS/JS in ASP.NET MVC?

So I was reading this stackoverflow post about "autoversioning" in ASP.NET MVC for CSS/JS files and was wondering what the "best" strategy is to do this.
The solution provided inserts an assembly number - which means everytime you publish - it will change EVERY SINGLE file which is not ideal because if you make modifications to just 1 *.css or *.js then it will change each and every file.
1) How can it be done just for "single files" instead of using site wide assembly using modification date or something on IIS7 ?
2) Also if I have some sort of "static" asset like - http://static.domain.com/js/123.js - how can I use rewrite to send the latest file for a request if someone has integrated this static link onto their site ?
i.e. http://static.domain.com/js/123.js is the link and when a request comes for this - check and send latest file ?
ASP.NET 4.5+ comes with a built-in bundling & minification framework
which is designed to solve this problem.
If you absolutely need a simple roll-your-own solution you can use the answer below, but I would always say the correct way is to use a bundling & minification framework.
You can modify the AssemblyInfo.cs file like so:
Change
[assembly: AssemblyVersion("1.0.0.0")]
to
[assembly: AssemblyVersion("1.0.*")]
This means that every time the project is built, it will have a new assembly version which is higher than the previous one. Now you have your unique version number.
Create an UrlHelperExtension class that will help get this information when needed in the views:
public static class UrlHelperExtensions
{
public static string ContentVersioned(this UrlHelper self, string contentPath)
{
string versionedContentPath = contentPath + "?v=" + Assembly.GetAssembly(typeof(UrlHelperExtensions)).GetName().Version.ToString();
return self.Content(versionedContentPath);
}
}
You can now easily add a version number to your views in the following manner:
<link href="#Url.ContentVersioned("style.css")" rel="stylesheet" type="text/css" />
When viewing your page source you will now have something that looks like
<link href="style.css?v=1.0.4809.30029" rel="stylesheet" type="text/css" />
UPDATE: The previous version did not work on Azure, I have simplified and corrected below. (Note, for this to work in development mode with IIS Express, you will need to install URL Rewrite 2.0 from Microsoft http://www.iis.net/downloads/microsoft/url-rewrite - it uses the WebPi installer, make sure to close Visual Studio first)
If you would like to change the actual names of the files, rather than appending a querystring (which is ignored by some proxies / browsers for static files) You can follow the following steps: (I know this is an old post, but I ran across it while developing a solution:
How to do it: Auto-increment the assembly version every time the project is built, and use that number for a routed static file on the specific resources you would like to keep refreshed. (so something.js is included as something.v1234.js with 1234 automatically changing every time the project is built) - I also added some additional functionality to ensure that .min.js files are used in production and regular.js files are used when debugging (I am using WebGrease to automate the minify process) One nice thing about this solution is that it works in local / dev mode as well as production. (I am using Visual Studio 2015 / Net 4.6, but I believe this will work in earlier versions as well.
Step 1: Enable auto-increment on the assembly when built
In the AssemblyInfo.cs file (found under the "properties" section of your project change the following lines:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
to
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
Step 2: Set up url rewrite in web.config for files with embedded version slugs (see step 3)
In web.config (the main one for the project) add the following rules in the <system.webServer> section I put it directly after the </httpProtocol> end tag.
<rewrite>
<rules>
<rule name="static-autoversion">
<match url="^(.*)([.]v[0-9]+)([.](js|css))$" />
<action type="Rewrite" url="{R:1}{R:3}" />
</rule>
<rule name="static-autoversion-min">
<match url="^(.*)([.]v[0-9]+)([.]min[.](js|css))$" />
<action type="Rewrite" url="{R:1}{R:3}" />
</rule>
</rules>
</rewrite>
Step 3: Setup Application Variables to read your current assembly version and create version slugs in your js and css files.
in Global.asax.cs (found in the root of the project) add the following code to protected void Application_Start() (after the Register lines)
// setup application variables to write versions in razor (including .min extension when not debugging)
string addMin = ".min";
if (System.Diagnostics.Debugger.IsAttached) { addMin = ""; } // don't use minified files when executing locally
Application["JSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.','0') + addMin + ".js";
Application["CSSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.', '0') + addMin + ".css";
Step 4: Change src links in Razor views using the application variables we set up in Global.asax.cs
#HttpContext.Current.Application["CSSVer"]
#HttpContext.Current.Application["JSVer"]
For example, in my _Layout.cshtml, in my head section, I have the following block of code for stylesheets:
<!-- Load all stylesheets -->
<link rel='stylesheet' href='https://fontastic.s3.amazonaws.com/8NNKTYdfdJLQS3D4kHqhLT/icons.css' />
<link rel='stylesheet' href='/Content/css/main-small.#HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/medium.#HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/large.#HttpContext.Current.Application["CSSVer"]' />
#RenderSection("PageCSS", required: false)
A couple things to notice here: 1) there is no extension on the file. 2) there is no .min either. Both of these are handled by the code in Global.asax.cs
Likewise, (also in _Layout.cs) in my javascript section: I have the following code:
<script src="~/Scripts/all3bnd100.min.js" type="text/javascript"></script>
<script src="~/Scripts/ui.#HttpContext.Current.Application["JSVer"]" type="text/javascript"></script>
#RenderSection("scripts", required: false)
The first file is a bundle of all my 3rd party libraries I've created manually with WebGrease. If I add or change any of the files in the bundle (which is rare) then I manually rename the file to all3bnd101.min.js, all3bnd102.min.js, etc... This file does not match the rewrite handler, so will remain cached on the client browser until you manually re-bundle / change the name.
The second file is ui.js (which will be written as ui.v12345123.js or ui.v12345123.min.js depending on if you are running in debug mode or not) This will be handled / rewritten. (you can set a breakpoint in Application_OnBeginRequest of Global.asax.cs to watch it work)
Full discussion on this at: Simplified Auto-Versioning of Javascript / CSS in ASP.NET MVC 5 to stop caching issues (works in Azure and Locally) With or Without URL Rewrite (including a way to do it WITHOUT URL Rewrite)
1)
Use file modification time instead. Here's an example:
public static string GeneratePathWithTime(string cssFileName)
{
var serverFilePath = server.MapPath("~/static/" + cssFileName);
var version = File.GetLastWriteTime(serverFilePath).ToString("yyyyMMddhhmmss");
return string.Format("/static/{0}/{1}", version, cssFileName);
}
This will generate a path like "/static/201109231100/style.css" for "style.css" (assuming the your style.css is located in the static directory).
You'll then add a rewrite rule in IIS to rewrite "/static/201109231100/style.css" to "/static/style.css". The version number will only be changed when the css file has been modified and only applies to modified files.
2)
You can handle the request to 123.js via an HttpModule and send the latest content of it, but I don't think you can guarantee the request gets the latest version. It depends on how the browser handles its cache. You can set an earlier expiration time (for example, one minute ago) in your response header to tell the browsers to always re-download the file, but it's all up to the browser itself to decide whether to re-download the file or not. That's why we need to generate a different path for our modified files each time we updated our files in your question 1), the browser will always try to download the file if the URL has never been visited before.
I wrote a Url Helper which does the CacheBusting for me.
public static string CacheBustedContent(this UrlHelper helper, string contentPath)
{
var path = string.Empty;
if (helper.RequestContext.HttpContext.Cache["static-resource-" + contentPath] == null)
{
var fullpath = helper.RequestContext.HttpContext.Server.MapPath(contentPath);
var md5 = GetMD5HashFromFile(fullpath);
path = helper.Content(contentPath) + "?v=" + md5;
helper.RequestContext.HttpContext.Cache.Add("static-resource-" + contentPath, path, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(24, 0, 0), System.Web.Caching.CacheItemPriority.Default, null);
}
else
{
path = helper.RequestContext.HttpContext.Cache["static-resource-" + contentPath].ToString();
}
return path;
}
You could replace the GetMD5HashFromFile() with CRC or any other sort of call which generates a unique string based on the contents or last-modified-date of the file.
The downside is this'll get called whenever the cache is invalidated. And if you change the file on live somehow, but don't reset the application pool, you'll probably need to touch the web.config to get it to reload correctly.
You might want to have a look at Dean Hume's Blogpost MVC and the HTML5 Application Cache. In that post, he points out an elegant way of automatically handling versioning per request, using a class library of #ShirtlessKirk:
#Url.Content("~/Content/Site.css").AppendHash(Request)
This question is really old now, but if anyone stumbles upon it, here's to my knowledge the current state of the art:
In ASP.NET Core you can use TagHelpers and simply add the asp-append-version attribute to any <link> or <script> tag:
<script src="~/js/my.js" asp-append-version="true"></script>
For both ASP.NET Core and Framework there is a NuGet Package called WebOptimizer (https://github.com/ligershark/WebOptimizer). It allows for both bundling and minification, and will also append a content-based version string to your file.
If you want to do it yourself, there is the handy IFileVersionProvider interface, which you can get from your IServiceProvider in .NET Core:
// this example assumes, you at least have a HttpContext
var fileVersionProvider = httpContext.RequestServices.GetRequiredService<IFileVersionProvider>();
string path = httpContext.Content("/css/site.css");
string pathWithVersionString = fileVersionProvider.AddFileVersionToPath(httpContext.Request.PathBase, path);
For .NET Framework, you can get the FileVersionProvider source from here: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Razor/src/Infrastructure/DefaultFileVersionProvider.cs
You will have to do some work, like replacing the Cache with MemoryCache.Default or a ConcurrentDictionary or something, but the 'meat' is there.

Display Images From a file System using Richfaces + Spring Webflow

I am not able to display images from the file system in the xhtmls using <h:graphicImage> tag. I am using Spring webflow 2.0 and Richfaces 3.3.3
Should I write a separate servlet to serve the images from the file system ?
I looked into <a4j:mediaOutput> tag . Can I use this ? since createContent requires us to specify a method that will be used for content creating. I am unsure if we can use the flow variables/beans to execute methods in the tag.
You can always fetch the images placing under Web Pages folder
<h:graphicImage url="#{facesContext.externalContext.requestContextPath}\your_img_path_under_Web_pages" id="img" />
If you use <a4j:mediaOutput> tag, then yes you should give method in createContent which will draw the image.
<a4j:mediaOutput element="img" createContent="#{serviceBean.method}" value="#{dataBean}" mimeType="image/jpg" />
public void userImage(OutputStream out, Object data) throws IOException {/*your method body*/}

Resources