Archive

Posts Tagged ‘URL’

HowTo: Reset browser cache of CSS files upon ASP.net MVC app publish

On an ASP.net MVC webapp I’m maintaining, I had the issue that due to caching of older CSS (stylesheet) files in the browser, if the user didn’t press F5/refresh, it wasn’t showing you some message (since I had added the class .center-horiz-vert in the CSS that didn’t exist in the older cached css the browser had).

Instead of changing web.config to stop cachine of CSS files (in which case it would bring the CSS on every page load which is an overkill), I expanded on an idea mentioned by Maxim Kornilov on SO (https://stackoverflow.com/a/12992813/903783), on making the CSS URLs webapp version specific.

I added a fake version parameter to the URLs with the build number as value so that till I publish a new build the browser caches the CSS, but when I upload a new build it brings the new one since it cache with the url as a key (that now includes the build number as a dummy url parameter that the webserver will ignore and just fetch the CSS file when requested)

Maxim’s example was in ASP/ASP.net WebForms syntax instead of MVC’s and Razor Pages’ newer Razor syntax), so I contributed my solution for the case of an ASP.net MVC webapp that wants to serve a fresh copy of CSS files on every new build that you publish (will do this whether the CSS file has changed or not) so that browsers don’t use older cached copies of the file. Obviously this expands to any kind of files you link/load into your webpages via a URL.

1) Added to the webapp’s main class (was called MvcApplication) in Global.asax.cs

#region Versioning

public static string Version => 
typeof(MvcApplication).Assembly.GetName().Version.ToString();
//note: syntax requires C# version >=6 public static DateTime LastUpdated =>
File.GetLastWriteTime(typeof(MvcApplication).Assembly.Location); #endregion

the someProperty => someReadOnlyExpression syntax is just shorthand for someProperty { get { return … ;} } possible since C# 6

2) in its Content/_Layout.cshtml file I used to have the following to show build number and build datetime (based on the webapp’s main assembly) on the page footer:

Version @ViewContext.Controller.GetType().Assembly.GetName().Version 
(@string.Format("{0:yyyy/MM/dd-HH:mm:ss}",
@File.GetLastWriteTime(ViewContext.Controller.GetType().Assembly.Location)))

which I changed to the simpler:

Version @somewebappname.MvcApplication.Version
(@string.Format("{0:yyyy/MM/dd-HH:mm:ss}",
somewebappname.MvcApplication.LastUpdated))

3) it was loading the CSS via hardcoded link in _Layout.cshtml (still refactoring it) which I changed to:

<link href='@Url.Content("~/Content/Site.css?version=" + 
somewebappname.MvcApplication.Version)' rel="stylesheet" type="text/css" />

so if one right-clicks in the webpage and they do view source they see:

<link href='/Content/Site.css?version=2.1.5435.22633' 
rel="stylesheet" type="text/css" />

that is the CSS url is version specific thanks to the dummy parameter version

If a random number was used instead it would fetch the CSS at every page load which is usually undesired, especially if you are already pushing a new webapp build instead of individual page changes to the web server (so that you do have access to a build number that you can inject into URLs).

Note that to achieve auto-incrementing of build number, at Properties/AssemblyInfo.cs I have (see How to have an auto incrementing version number (Visual Studio)?):

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision 
// and Build Numbers by using the '*' as shown below: [assembly: AssemblyVersion("1.0.*")] //[assembly: AssemblyFileVersion("1.0.*")]
// don't use boh AssemblyVersion and AssemblyFileVersion with auto-increment

HowTo: Use WordPress Permalinks on IIS

at http://zachis.it/blog/7-dangers-of-using-windows-server-on-a-wordpress-installation/

the thing that guy says about Permalinks isn’t accurate at all (not that the other things that he says are any accurate that is). WordPress Codex have documentation on how to configure URL rewriting in web.config that is necessery for Permalinks to work in IIS.

e.g. at http://ClipFlair.net, if you press the "about" icon you’re taken to a WordPress site that runs on IIS and uses permalinks fine and hides the index.php too from the URL

in its web.config I have the following:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>

        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" prefixLanguageFilePath="" path="/index.php?error=404" responseMode="ExecuteURL" />
        </httpErrors>

        <!– Needed for WordPress Permalinks –>
        <rewrite>
            <rules>

                <rule name="Main Rule" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <!– <action type="Rewrite" url="index.php/{R:0}" /> –>
                    <action type="Rewrite" url="index.php" />
                </rule>

            </rules>
        </rewrite>

        <defaultDocument>
            <files>
                <clear />
                <add value="index.html" />
                <add value="index.php" />
                <add value="default.aspx" />
            </files>
        </defaultDocument>

    </system.webServer>
</configuration>

Gotcha: JS replace on document.location fails, use document location.href

This is my contribution to:
http://stackoverflow.com/questions/2652816/what-is-the-difference-between-document-location-href-and-document-location

Here is an example of the practical significance of the difference and how it can bite you if you don’t realize it (document.location being an object and document.location.href being a string):

We use MonoX Social CMS (http://mono-software.com) free version at http://social.ClipFlair.net and we wanted to add the language bar WebPart at some pages to localize them, but at some others (e.g. at discussions) we didn’t want to use localization. So we made two master pages to use at all our .aspx (ASP.net) pages, in the first one we had the language bar WebPart and the other one had the following script to remove the /lng/el-GR etc. from the URLs and show the default (English in our case) language instead for those pages

<script>
  var curAddr = document.location; //MISTAKE
  var newAddr = curAddr.replace(new RegExp("/lng/[a-z]{2}-[A-Z]{2}", "gi"), "");
  if (curAddr != newAddr)
    document.location = newAddr;
</script>

But this code isn’t working, replace function just returns Undefined (no exception thrown) so it tries to navigate to say x/lng/el-GR/undefined instead of going to url x. Checking it out with Mozilla Firefox’s debugger (F12 key) and moving the cursor over the curAddr variable it was showing lots of info instead of some simple string value for the URL. Selecting Watch from that popup you could see in the watch pane it was writing "Location -> …" instead of "…" for the url. That made me realize it was an object

One would have expected replace to throw an exception or something, but now that I think of it the problem was that it was trying to call some non-existent "replace" method on the URL object which seems to just give back "undefined" in Javascript.

The correct code in that case is:

<script>
  var curAddr = document.location.href; //CORRECT
  var newAddr = curAddr.replace(new RegExp("/lng/[a-z]{2}-[A-Z]{2}", "gi"), "");
  if (curAddr != newAddr)
    document.location = newAddr;
</script>
Categories: Posts Tags: , , , , , , ,

Gotcha: Image component not loading remote URLs during debugging

At ClipFlair’s Image component I use the following XAML to make it show an image from a URL that its ViewModel holds at a property named “Source”, of type Uri (URI = Uniform or Universal Resource Identifier in W3C parlance, something like a superset of the old classic URLs).

<Image Name="imgContent"
       HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
       Source="{Binding Source, Mode=OneWay}"
       Stretch="{Binding Stretch, Mode=OneWay}"
       >

I’ve had issues in the past with that component not loading an image, a tricky issue was when I had used Mode=TwoWay when data-binding to Source property – that was disastrous, since the Source property expects an ImageSource and just “plays it clever” internally, also accepting a conversion from a Uri. So when doing reverse binding too, you’d end up getting a null value at respective the ViewModel property.

So when it recently started not showing the test image (from a remote URL) that I had been using, I started wondering if it was some regression of that older bug, but couldn’t find some change in the respective code, plus in the Visual Studio XAML designer the component would load and display the remote image fine.

It turned out to be an issue with Silverlight’s security policy regarding cross-site access. The Image control is supposed to be able to load images from any remote URL (without the remote web server needing to have a ClientAccessPolicy.xml file for example to allow it, as is the case with the WebClient class), however I had recently found out that if at your Silverlight project you have selected at the “Debug”  tab the “Dynamically generate a test page” option, the Image control wouldn’t load remote images.

What I didn’t know was that even the “Out-of-browser application option there won’t let the Image control load remote images if you don’t select the web project that goes with your Silverlight project (supposing you have them in the same Visual Studio solution), but you happen to select your Silverlight project instead from the dropdown list.

I had changed that option without thinking it might cause an issue while doing other changes in the project. That’s why one should try to do a minimal set of related changes only and test again thoroughly each time (if only they had the time available to do it), so that they can spot such issues early and be able to relate newly introduced bugs to the recent small set of changes, helping to track down the exact change that caused the unwanted behaviour.

image

HowTo: Tell AddThis to not append tracking suffix on addressbar

ClipFlair’s project description website is based on WordPress (a quite extensible blogging platform based on PHP). The other day we had an issue with the AddThis Plugin for WordPress, which was adding tracking suffices (in the form #.UAxxxxx) to the end of our URLs on the browser address bar.

Moreover this wasn’t occuring in Internet Explorer, since it doesn’t support the History API – probably for more security against Phishing scams – that the AddThis plugin uses for its Address Bar Shares tracking feature.

At first I didn’t spot that setting at the Settings/AddThis menu in WordPress dashboard and was looking into configuring it manually (it’s “addthis_addressbar” boolean setting, probably kept in wp_config.php), but eventually our designer spotted it at the “Advanced” tab there (wonder how I missed that 2nd tab altogether in the first place).

addthis-settings-screen

Collection of Smooth Streaming Video URLs

Here are some Smooth Streaming URLs I found on the Internet that you could use during development to test your smooth streaming players (like those based on SMF).

If you haven’t yet started building your SMF-based player you can try the following URLs here: http://www.smoothhd.com/livetestplayer/

Update: you can also try Smooth Stream URLs at ClipFlair Studio Silverlight-based application, turning over its Clip component (using the “Wrench” button on its titlebar) and pasting the Media URL there. Alternatively, you can launch it directly using a URL of the form http://studio.clipflair.net?video=http://smoothstreamer.doit.wisc.edu/doit-nms/BBB_carbon/BBB.ism/Manifest

http://smoothstreamer.doit.wisc.edu/doit-nms/BBB_carbon/BBB.ism/Manifest

http://streams.smooth.vertigo.com/BigBuckBunny_30sec/bigbuck.ism/manifest

http://streams.smooth.vertigo.com/elephantsdream/Elephants_Dream_1024-h264-st-aac.ism/manifest (this one also features multiple audio streams, director’s comments in english and also english and spanish dialogs)

http://playready.directtaps.net/smoothstreaming/TTLSS720VC1/To_The_Limit_720.ism/Manifest

http://playready.directtaps.net/smoothstreaming/SSWSS720H264/ SuperSpeedway_720.ism/Manifest

At the same test server one can also find two audio-only smooth streams:

http://playready.directtaps.net/smoothstreaming/ISMAAACLC/Taxi3_AACLC.ism/Manifest

http://playready.directtaps.net/smoothstreaming/ISMAAACHE/Taxi3_AACHE.ism/Manifest

http://mediadl.microsoft.com/mediadl/iisnet/smoothmedia/Experience/ BigBuckBunny_720p.ism/Manifest

http://ecn.channel9.msdn.com/o9/content/smf/smoothcontent/bbbwp7/big%20buck%20bunny.ism/manifest

http://ecn.channel9.msdn.com/o9/content/smf/smoothcontent/elephantsdream/ Elephants_Dream_1024-h264-st-aac.ism/manifest

http://video3.smoothhd.com.edgesuite.net/ondemand/Big%20Buck%20Bunny%20Adaptive.ism/Manifest

http://video3.smoothhd.com/ondemand/Turner_Sports_PGA.ism/Manifest

http://video3.smoothhd.com/ondemand/Turner_Sports_NASCAR.ism/Manifest

http://video3.smoothhd.com/ondemand/Turner_Sports_MLB.ism/Manifest

http://video3.smoothhd.com/ondemand/Akamai_ASP_Cutdown.ism/Manifest

http://video3.smoothhd.com/ondemand/mix1/mix1.ism/Manifest

http://video3.smoothhd.com/ondemand/mix2/mix2.ism/Manifest

http://video3.smoothhd.com/ondemand/Big%20Buck%20Bunny%20Adaptive.ism/Manifest

http://video3.smoothhd.com/ondemand/ElephantsDream.ism/Manifest

http://video3.smoothhd.com/ondemand/Got_Imagination_(Indo).ism/Manifest

http://video3.smoothhd.com/ondemand/Got_Imagination_(California).ism/Manifest

http://video3.smoothhd.com/ondemand/Coral_Reefs.ism/Manifest

http://video3.smoothhd.com/ondemand/eHow_Wakeboard.ism/Manifest

http://video3.smoothhd.com/ondemand/eHow_Baseball.ism/Manifest

http://video3.smoothhd.com/ondemand/eHow_Alligator.ism/Manifest

http://video3.smoothhd.com/ondemand/NBA.ism/Manifest

http://video3.smoothhd.com/ondemand/Changeling.ism/Manifest

http://video3.smoothhd.com/ondemand/Livestrong_ThyroidCancer.ism/Manifest

http://video3.smoothhd.com/ondemand/Livestrong_BeginnerGuideExercising.ism/Manifest

http://video3.smoothhd.com/ondemand/Livestrong_Autism.ism/Manifest

Also found some (probably) Bollywood movie:

http://az280594.vo.msecnd.net/athadu/athadu480.ism/Manifest

You can use the following search query to search for “.ism/Manifest”:
http://www.google.com/?q=%22http%22+%22.ism%2FManifest%22&oq=%22http%22+%22.ism%2FManifest%22

A good source found is http://www.smoothhd.com/content/smoothhd/smoothhd.xml

which seems to be from http://wwwns.akamai.com/hdnetwork/demo/silverlight/default.html

Some more URLs (use the unencrypted ones that write CLEAR) are found at:

http://playready.directtaps.net/smoothstreaming/

Gotcha: Silverlight’s Uri class constructor eats up part after last slash

Via trial and error, I recently found out that when creating a Uri combining another Uri and a suffix part (tried at Silverlight, but I guess it’s a .NET issue in general), it eats up the last part of the (first) Uri if it doesn’t end with "/".

That is, if you combine http://test.com/a with b.doc you get http://test.com/b.doc instead of http://test.com/a/b.doc that one might expect having used the Path.Combine of .NET on the local filesystem before (if hope I do remember well how that one behaves). So you have to make sure the first part of the path you combine has / at the end (e.g. http://test.com/a/ in the case above).

Personally I feel this is a bug at Uri class (since it breaks the least surprise principle [for developers with desktop experience at least]), but it may have been made so to follow some W3C suggestions or Javascript standard behaviour or whatever.

Example:

The following code will eat up part after last / (that is Uploads) instead of appending / (as Path would do on Windows).

const string STORAGE_URL = "http://test.com/Uploads"; //error: need "/" at end
Uri fileUri = new Uri(new Uri(STORAGE_URL), fileName + ".wav");

So, one can use instead:

const string STORAGE_URL = "http://test.com/Uploads";
Uri fileUri = new Uri(STORAGE_URL + "/" + fileName + ".wav");

Else fix the STORAGE_URL at the first sample to have "/" at the end (but this can break easily by changing the URL in the future and forgetting to add the trailing / or reading it from some configuration file and having the user enter a URL without a trailing / which can easily occur)

%d bloggers like this: