Stupid HTTP variable, HTTP_REFERER. It's spelt wrong for a start.
Anyway, to cut a long, stupid story short, an HTTP call invoked from a javascript window.location change will usually set the HTTP_REFERER variable on IIS because the browser sends a Referer header.
I say 'usually' because it DOESN'T FRIGGING WORK in IE8. IE9, FF, Chrome, fine. IE8, nope.
Sigh.
DaddyCode Team Blog
C# , ASP.NET, MVC, SQL, Sharepoint, JQuery and nowt else from a Web Developer in Leeds
15 Nov 2011
9 Nov 2011
Rockalldll.dll missing / not found error - Rockall Heap Manager on Windows 7
This week's mystery was a recurring error message in Windows 7 about a missing DLL - RockallDll.dll.
It sounded dodgy, and a quick google returned about a million nasty DLL sites purporting to offer a nice shiny replacement DLL, no doubt festooned with viruses and trojans.
So I didn't do that. I had to do some pretty deep searching to find out that this DLL was originally installed as part of Hermann Schinagl's Link Shell Extension that I installed ages ago. For some reason I had installed it on my E drive. Well, I don't know why it had stopped working, but I uninstalled it, downloaded the latest version and installed it on C drive instead.
Problem solved, woohoo. And I do recommend LSE as a quick way of creating symbolic links in Windows.
It sounded dodgy, and a quick google returned about a million nasty DLL sites purporting to offer a nice shiny replacement DLL, no doubt festooned with viruses and trojans.
So I didn't do that. I had to do some pretty deep searching to find out that this DLL was originally installed as part of Hermann Schinagl's Link Shell Extension that I installed ages ago. For some reason I had installed it on my E drive. Well, I don't know why it had stopped working, but I uninstalled it, downloaded the latest version and installed it on C drive instead.
Problem solved, woohoo. And I do recommend LSE as a quick way of creating symbolic links in Windows.
3 Nov 2011
IntelliType Pro 8, Media Keys and iTunes 10.5
I just got me a new MS Sidewinder X4 keyboard, and very swanky it is too. However, it requires Microsoft IntelliType Pro to work, and after installing that, I was annoyed to find that the Media Keys (Play, Pause, Prev Track, Next Track) didn't work with iTunes.
Here's what I found out.
Here's what I found out.
- iTunes control worked fine if I uninstalled IntelliType Pro, but this was no good because then I lost the use of the keyboard's Macro keys.
- By doing the trick of launching iTunes as administrator (right click on the iTunes icon - choose "Run as administrator") , iTunes can be controlled from the Media keys - But ONLY when iTunes is in Window Focus.
- Launching the IntelliType process (itype.exe) as administrator makes no difference.
However I have found a Heath Robinson / Rube Goldberg stylee solution!
HKTunes Portable is free software that launches iTunes for you and attaches custom key handlers to the Play/Pause, Next/Previous controls. So I configured that to use some wild, unlikely key combos, and then I set up those same key combos as Macros for the Media Keys in IntelliType Pro (Start > Microsoft Keyboard > Key Settings).
The only drawback is that you have to remember to launch HKTunes rather than iTunes, but I just replaced the pinned launcher in my task bar so it's not a problem. Wish Microsoft would sort out the underlying prob though!
UPDATE
I found a better solution! Check this guy's EXCELLENT MediaKeys app!
UPDATE UPDATE 23 April 2012
Looks like this is fixed as of Intellitype 8.2 (wasn't listed as Intellitype Pro for some reason?) and iTunes 10.6. GOOD.
UPDATE
I found a better solution! Check this guy's EXCELLENT MediaKeys app!
UPDATE UPDATE 23 April 2012
Looks like this is fixed as of Intellitype 8.2 (wasn't listed as Intellitype Pro for some reason?) and iTunes 10.6. GOOD.
30 Oct 2011
Keyboard Test utility for Windows 7
I have a duff keyboard, but I only proved it was duff by using a little utility to test it. Unfortunately, finding a Key Press Test application for windows 7 was right nightmare!
So I wrote one. Enjoy: Keyboard Tester.
So I wrote one. Enjoy: Keyboard Tester.
26 Sept 2011
jQuery Post a javascript array to ASP.NET MVC
I wanted to post a bunch of ID numbers to my MVC controller, which is sat waiting with the following signature:
However, this post needed to be generated from jQuery - specifically we're sending through the data ids of entities that correspond to "checked" checkboxes in a list. So what we need was a way of iterating through the list of checked checkboxes, getting the IDs into an array, and sending that through ajax to the server, to be picked up with the correct signature action.
The tricky bit was basically the construction of the javascript object literal in the map function: jQuery converts that array into the ajax querystring using its param() function, which requires name and value properties.
The result is that jQuery posts multiple values with the same name ('leadIds'), and MVC recognises that and converts them into an IList<int>.
public ActionResult UnParkLeads(IList<int> leadIds)
However, this post needed to be generated from jQuery - specifically we're sending through the data ids of entities that correspond to "checked" checkboxes in a list. So what we need was a way of iterating through the list of checked checkboxes, getting the IDs into an array, and sending that through ajax to the server, to be picked up with the correct signature action.
var leadIds = $('input.chkTileSelector:checked').map(function () {
return { name: 'leadIds', value: $(this).parents('div.Lead').data('id') };
}).get();
$.ajax({
url: '@Url.Action("UnParkLeads", "Lead")',
type: 'POST',
dataType: 'json',
data: leadIds,
success: function (result) {
ReloadResultGrid();
}
});
The tricky bit was basically the construction of the javascript object literal in the map function: jQuery converts that array into the ajax querystring using its param() function, which requires name and value properties.
The result is that jQuery posts multiple values with the same name ('leadIds'), and MVC recognises that and converts them into an IList<int>.
8 Sept 2011
Using OutputCache with PartialView in MVC 3, with programmatic invalidation usingVaryByCustom too!
I've had a fun morning trying to cache partial views inside a dynamic page with MVC 3. Specifically, a partial view in a razor layout page (i.e. masterpage) that shows some dynamically generated data which I would like to hold off from regenerating for 60 seconds or so, even if the user refreshes or navigates around the site.
So I create my partial view like this - here we generate the time to show when the view is being cached
MyPartial.cshtml
Then I create the controller action:
HomeController.cs
Then I amend my layout page to include the call to the PartialView:
MyMaster.cshtml
Well, that's all there is to it. The pitfalls I faced revolved around accidentally calling Html.Partial() from the layout page, which didn't work because it bypasses the controller attributes (i.e. it misses the OutputCache directive).
HOWEVER
Then I started wanting to reset the output cache when the underlying data changed, or when some user setting changed. So I knocked up this little solution using the OutputCache attribute's VaryByCustom property.
First a modification to the controller:
HomeController.cs
Every time OutputCache is called, it will check to see if that string has changed since last time. If it has changed, it invalidates the cache. "But it's a static string! How can it change?" I hear you cry. Yup, here's some voodoo magic. You can override a special method in global.asax that intercepts the call and returns ANOTHER string, wooo!
global.asax
WebApp.cs
So I create my partial view like this - here we generate the time to show when the view is being cached
MyPartial.cshtml
Timestamp: @DateTime.Now.ToLongTimeString()
Then I create the controller action:
HomeController.cs
[OutputCache(Duration = 60)]
public ActionResult MyPartial()
{
return PartialView();
}
Then I amend my layout page to include the call to the PartialView:
MyMaster.cshtml
Some header stuff
...
@Html.Action("MyPartial", "Home")
...
Some footer stuff
Well, that's all there is to it. The pitfalls I faced revolved around accidentally calling Html.Partial() from the layout page, which didn't work because it bypasses the controller attributes (i.e. it misses the OutputCache directive).
HOWEVER
Then I started wanting to reset the output cache when the underlying data changed, or when some user setting changed. So I knocked up this little solution using the OutputCache attribute's VaryByCustom property.
First a modification to the controller:
HomeController.cs
[OutputCache(Duration = 60, VaryByCustom = "WebApp.OutputCacheKey")]
public ActionResult MyPartial()
{
return PartialView();
}
Every time OutputCache is called, it will check to see if that string has changed since last time. If it has changed, it invalidates the cache. "But it's a static string! How can it change?" I hear you cry. Yup, here's some voodoo magic. You can override a special method in global.asax that intercepts the call and returns ANOTHER string, wooo!
global.asax
public override string GetVaryByCustomString(HttpContext context, string arg)
{
if (arg == "WebApp.OutputCacheKey")
{
return WebApp.OutputCacheKey;
}
else
{
return base.GetVaryByCustomString(context, arg);
}
}
Now, we need to implement this WebApp thing. It's just an approach I like to have a static class knocking around my web application that allows me to access stuff from one central place, like strongly-typed accessors for session variables, or my per-request EF datacontext. But for these purposes it would just look like this:WebApp.cs
public static class WebApp
{
internal static string OutputCacheKey
{
get
{
if (HttpContext.Current.Session["WebApp.OutputCacheKey"] == null)
{
ResetOutputCache();
}
return HttpContext.Current.Session["WebApp.OutputCacheKey"].ToString();
}
}
internal static void ResetOutputCache()
{
HttpContext.Current.Session["WebApp.OutputCacheKey"] = Guid.NewGuid().ToString();
}
}
So, what we have now is an easy way to programatically tell the OutputCache to clear itself, with a simple call from anywhere in your controller code:WebApp.ResetOutputCache();Simples!
2 Sept 2011
MVC 3 DropDownListFor not selecting an item (Title property of model)
Have you got a problem with MVC 3 where your model has a property that is definitely set, but when you use it in a DropDownListFor, the value doesn't get selected from your SelectList? Me too, and I've solved it.
I had a viewmodel like so:
and in my View, I was showing it like this:
HOWEVER, in my View, I also had this lurking:
Yup, with DropDownListFor at least, ViewBag properties are used in preference to model properties when MVC tries to find the selected value. It couldn't find "My Lovely Page" in the SelectList, and so nothing was selected. When I changed my ViewBag property to ViewBag.PageTitle instead, everything started working properly.
I had a viewmodel like so:
[Required]
public string Title { get; set; }
public List<SelectListItem> TitleSelectList
{
get
{
var selectList = new List<SelectListItem>();
selectList.AddRange(new string[] { "Mr", "Mrs", "Miss", "Ms", "Dr", "Other" }.Select(item => new SelectListItem() { Text = item, Value = item }));
selectList.Insert(0, new SelectListItem { Text = "Choose...", Value = "" });
return selectList;
}
}
and in my View, I was showing it like this:
@Html.DropDownListFor(model => model.Title, Model.TitleSelectList)
HOWEVER, in my View, I also had this lurking:
@{
ViewBag.Title = "My Lovely Page";
}
Yup, with DropDownListFor at least, ViewBag properties are used in preference to model properties when MVC tries to find the selected value. It couldn't find "My Lovely Page" in the SelectList, and so nothing was selected. When I changed my ViewBag property to ViewBag.PageTitle instead, everything started working properly.
10 Aug 2011
Unable to use SQL Server because ASP.NET version 2.0 Session State is not installed
Setting up a new MVC 3 (ASP.NET 4) site, using SQL Session State. Got the message:
Unable to use SQL Server because ASP.NET version 2.0 Session State is not installed on the SQL server
But I *had* set up Session State, so this was perplexing.
Turns out this was because I had only given the ASP.NET user db_datareader and db_datawriter permissions on the Session State database. Those permissions don't allow the user to EXEC sprocs. I gave the user db_owner perms and all was well.
Stupid unhelpful error message!
Unable to use SQL Server because ASP.NET version 2.0 Session State is not installed on the SQL server
But I *had* set up Session State, so this was perplexing.
Turns out this was because I had only given the ASP.NET user db_datareader and db_datawriter permissions on the Session State database. Those permissions don't allow the user to EXEC sprocs. I gave the user db_owner perms and all was well.
Stupid unhelpful error message!
Linq select vs Enumerable.Select()
I found the MSDN docs a bit confusing with this, so here's a brief aide memoire about how to transform a list of one Type to a list of another, using Linq and also Enumerable Linq methods.
In this case I'm transforming from a List of EF Entities (called promotions here) to a list of MVC SelectListItems.
Standard Linq stylee
Enumerable Linq Method stylee
To get a List out, you just do query.ToList().
In this case I'm transforming from a List of EF Entities (called promotions here) to a list of MVC SelectListItems.
Standard Linq stylee
var query = from promo in promotions
select new SelectListItem { Text = promo.Name, Value = promo.Id.ToString() };
Enumerable Linq Method stylee
var query = promotions.Select(promo => new SelectListItem() { Text = promo.Name, Value = promo.Id.ToString() });
To get a List out, you just do query.ToList().
13 Jul 2011
Load-Balanced IIS 7.5 Web Server ASP.NET SQL Session State problem
We had a problem recently with an ASP.NET website where the users' sessions were behaving oddly - session data appearing, disappearing and re-appearing.
As the site is hosted on two webservers using network load-balancing, I figured the problem must have something to do with that, but I was puzzled because I thought my configuration's use of a single, central, standard ASP.NET SQL Session State database would remove such problems.
Well, apparently this is only true if IIS is set up correctly and consistently on all your webserver machines. You see, if you check the AspStateTempApplications table in the AspState database, you'll see reference to website Instance IDs (e.g. /W3SVC/1/Root, /W3SVC/2/Root etc). So, ASP.NET hooks up your browser's session cookie to your session data using the Instance ID of the website serving you.
But what if the load-balanced servers host several sites, and due to the order of setup, your site on one server has a different Instance ID to the one on the other? That's right, you end up getting served up with different session data depending which server the load-balancer allocates to your HTTP request.
So, how to fix the prob? You just need to get the IIS Instance IDs in sync on the 2 servers. For IIS 6 there's a script you can run.
For IIS 7.5 however, you can't use adsutil.vbs style solutions anymore. However that's because the Metabase is old-hat and we rock config files now baby! You can set the id of a site using its id attribute found in C:\Windows\System32\inetsrv\config\applicationHost.config. You need admin privs to edit that, and need to restart IIS afterwards.
Easier still,
1. Remote Desktop onto server 1, open IIS Mgr, click on the problem Site and choose Advanced Settings in the sidebar.
2. Change the ID to something unique e.g. 10. Click OK.
3. Restart the web service (c:\windows\system32\iisreset /restart)
Do the same for server 2 (ensure the Site ID is the same as on server 1).
Again, restart the website after the change for it to take effect.
As the site is hosted on two webservers using network load-balancing, I figured the problem must have something to do with that, but I was puzzled because I thought my configuration's use of a single, central, standard ASP.NET SQL Session State database would remove such problems.
Well, apparently this is only true if IIS is set up correctly and consistently on all your webserver machines. You see, if you check the AspStateTempApplications table in the AspState database, you'll see reference to website Instance IDs (e.g. /W3SVC/1/Root, /W3SVC/2/Root etc). So, ASP.NET hooks up your browser's session cookie to your session data using the Instance ID of the website serving you.
But what if the load-balanced servers host several sites, and due to the order of setup, your site on one server has a different Instance ID to the one on the other? That's right, you end up getting served up with different session data depending which server the load-balancer allocates to your HTTP request.
So, how to fix the prob? You just need to get the IIS Instance IDs in sync on the 2 servers. For IIS 6 there's a script you can run.
For IIS 7.5 however, you can't use adsutil.vbs style solutions anymore. However that's because the Metabase is old-hat and we rock config files now baby! You can set the id of a site using its id attribute found in C:\Windows\System32\inetsrv\config\applicationHost.config. You need admin privs to edit that, and need to restart IIS afterwards.
Easier still,
1. Remote Desktop onto server 1, open IIS Mgr, click on the problem Site and choose Advanced Settings in the sidebar.
2. Change the ID to something unique e.g. 10. Click OK.
3. Restart the web service (c:\windows\system32\iisreset /restart)
Do the same for server 2 (ensure the Site ID is the same as on server 1).
Again, restart the website after the change for it to take effect.
Subscribe to:
Posts (Atom)
If I helped you out today, you can buy me a beer below. Cheers!