Showing posts with label Tips and Tricks. Show all posts
Showing posts with label Tips and Tricks. Show all posts

Thursday, 23 May 2013

Session Expiration in ASP.NET MVC

The other day a colleague of mine asked me for some help fixing a bug. The issue was that our web sessions are configured to last 30 minutes and after 30 minutes of inactivity ASP.NET should redirect the user back to the login page (in our case at least), but this was not happening in our latest ASP.NET MVC website. I wandered over to his screen and saw it for myself, it just let the request complete as usual, defying my understanding of how session expiration worked.

So I searched around and found out the following:

Authorization

In our case the session timeout and the forms authentication timeout are different: sessions timeout at 30 minutes while forms authentication can last much longer. So it seems that what ASP.NET MVC does by default (using the [Authorize] attribute) is to authorize the request coming in because that has not expired yet but a new session is set up for the user. This means that any previous data you had stored is missing which will no doubt affect the functionality of your website.

Solution

So how can we solve this? This solution is actually quite simple, a custom authorization attribute can be implemented which can both authorize and check the session. For example let’s assume that your session contains something which you know means that a user is logged in, for instance a user ID; that means you can write something like the following:

[AttributeUsage(
AttributeTargets.Class
| AttributeTargets.Method,
Inherited
= true,
AllowMultiple
= true
)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}

// Authenticate the user using Forms Authentication
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
}

// Now check that a new session has not been created, if we are missing
// some critical session variables then we assume that the session
// expired and do not allow the request to continue
if (httpContext.Session["UserId"] == null)
{
return false;
}

return true;
}
}

By applying this custom authorization attribute to your controllers/actions you will now be able to check both forms authentication and session expiration at the same time.

Friday, 18 January 2013

ASP.NET Websites and Sub-Folders in Project Output Paths

This will be a quick post but I wanted to get it out there while I remembered.

Yesterday and this morning at work I was faced with an unusual problem. One of our ASP.NET MVC websites, which worked perfectly fine until now, decided it did not want to compile. Specifically it was the Razor engine which wasn’t happy; the actual project would compile fine in Visual Studio but as soon as I ran it a runtime compiler error would happen immediately because a collection of Razor helpers could not find our own assembly as a reference. What’s going on?

So I searched and searched and found all sorts of questions on StackOverflow explaining how to add an assembly reference to the Web.config file and add it to the specific Razor Web.config settings but that wasn’t helping me at all; it simply refused to run.

Out of sheer frustration I started comparing the project folder to a previous version to see what could have possibly changed to break it and the only difference I found was that another developer had checked in a change which would compile the project output from “bin\” to “bin\{Configuration}”. Surely that can’t be the cause, can it?

Actually it was, and this blog post by Adam Craven explained why:

Intellisense in Razor for Custom Types and Helpers

Now most Visual Studio project templates will setup the output path of the compiled files to be “bin\{Configuration}”, which sounds sensible to me. Apparently ASP.NET projects don’t do this because the ASP.NET runtime will not find your own assemblies for some reason – as I said, the blog post above explains it better than I could.

So all in all a frustrating morning was resolved simply by changing the project output path. It’s funny how the simplest thing can completely break your code.

Wednesday, 14 November 2012

Forcibly Uninstall Apps from Windows 8

I took the plunge a couple of weeks ago and upgraded to Windows 8. It takes some getting used to but overall I’m mostly happy with it. Except when it did something very unusual with the Metro apps (I refuse to use another name since everyone by now knows what “Metro” means).

For those who don’t know when updates are available for Metro apps they appear in the Windows Store, a little number appears on the live tile. One day I found that there were updates available for all the built-in apps such as Mail, Calendar, Bing etc. So I dutifully went to start the update process, found it was taking a while as there were quite a few, and just left it to it.

To be fair I might have messed up my system myself but while this was happening I thought “I don’t need Travel, Sports or anything like that. I’ll just keep the ones I’m interested in”. So I uninstalled the apps I didn’t care about whilst they were still updating.

In retrospect I should have known better – I’m effectively classed as a power user! As a result of my blunder I ended up with nearly all the apps that were updated being wiped from the system, including some of the ones that did matter to me. Here’s the interesting part though: when I went back to the Windows Store to try and install them again I couldn’t. This is what I saw:

So the Store thinks it is already installed. So why when I search for it does this happen?

Something in Windows clearly thinks I have the app installed. Now in the past I would have known to check certain folders like Program Files or delve into the registry to see if some sort of metadata was lying around, but Windows 8 changes things up a bit: these Metro apps seem completely self-contained and sitting in the WindowsApps folder which is quite secure and doesn’t even let me read it by default. So how can I remove these hidden settings to get Windows to play nice again?

Fortunately after some Googling I found the answer on this forum which I will explain in detail below. In this example I’m going to re-install the Bing app despite the Store telling me that I already have it.

First you need to open up an elevated PowerShell console. Simply:

  1. Press the Win-key to get you to the Start Screen.
  2. Start typing “Powershell”
  3. Right-click on “Windows PowerShell” and click on “Run as administrator” in the menu that appears at the bottom of the screen.

Now you can run this cmdlet to see what Metro apps Windows considers to be installed:

Get-AppxPackage -allusers


This should give you a list like in the image below:




Now that you’ve got the details of the app you can run another cmdlet to remove it. In my case I did this:


Remove-AppxPackage Microsoft.Bing_1.5.1.251_x64__8wekyb3d8bbwe


You’ll notice that you have to use the PackageFullName value that is provided in order for the cmdlet to work.


Once that was done I went back to the Windows Store and checked that it worked:




In my case I simply repeated these steps until I had cleared up my mess and managed to get everything I wanted back.


I think it’s quite good that there is actually a way to uninstall something in an automated fashion. Regardless, this trick got me out of a hole so I’m sure someone else might benefit from re-learning Windows tricks like I’m doing.

Tuesday, 26 June 2012

Using Pocket and its Bookmarklet on Windows Phone 7

I have a Windows Phone 7 smartphone, a HTC Trophy to be exact. I can't speak for iPhones or Android phones - since I've never used them - but I like my WP7 phone (just not in a religious way). It presents everything in a nicely laid out fashion, I really like the Live Tiles and how they give me information without having to go into apps to find out, and best of all for me it seems really simple; it just does enough for what I need it to do.

But this isn't a post about how I love Windows Phone 7, this is a post about a common scenario I face day to day.

Reading It Later

When on the go I'll read through my Facebook and Twitter feeds using WP7's built in social network integration - it's not fancy but boy is it faster than any dedicated Facebook/Twitter app you'd care to try. OK, enough of the hard sell, time to focus...

Often I'll come across a link that someone has posted pointing to a blog post/news article/video/whatever that I'll be interested in, which of course will pop open in IE Mobile. Sometimes I'll read it, but other times I just want to "read it later" - either the article is too small for a phone screen to read easily, I don't have time to read it all, or it's a video and I would rather not eat up my data contract.

So my current system of saving these one-off things to look at is to email the link to myself - very easy to do in IE Mobile using the "Share" menu option - but then I'll end up with loads of emails in my inbox which are just reminders for me to do something. I just feels like there must be a better way...

Enter Pocket

I asked friends and looked around and eventually settled on Pocket (formally Read It Later). All it does is collect links that you save via a number of methods which you can then look at later. I went with this one because although it doesn't have much in the way of direct WP7 integration there are at least two simple ways that I can save links to my Pocket account from my phone:
  1. Email the link to Pocket. Again quite simple thanks to the "Share" menu.
  2. Add a bookmarklet to your favourites to magically save links.
But if you look at the instructions they give, it tells you to drag and drop the bookmarklet to your bookmarks bar because they are assuming you are doing this from your PC, which is not something you can do on a touchscreen.

Adding Bookmarklets to your Phone

Fortunately you can add bookmarklets to your phone's browser, it's just not as intuitive. Here's how I did it for the Pocket bookmarklet but I assume the same process can be applied for other sites:
  1. From your phone's browser, go to the Pocket bookmarklet page to see the button that has the bookmarklet link.
  2. Press and hold the bookmarklet button to get the "right click" menu to appear, then tap "Copy Link".
  3. Tap the "..." on the browser's menu bar to see the main menu and tap "add to favourites".
  4. Clear everything in the Web Address field and paste in the bookmarklet link - a long string of JavaScript code.
  5. Enter a memorable name for it - I've called mine "+ Pocket" like the website suggests - and save it.
That's it, you've now got a working bookmarklet in your phone's favourite list. Now any time you see something on your phone's browser that you want to read later, just go to the favourites menu and tap the bookmarklet to save it to your Pocket account.

Sunday, 8 April 2012

SQL Server - Delete Millions of Rows Without Pummeling the Transaction Log

Here's a problem that I've encountered several times and struggled with before I settled on this solution.

Let's say that you have a table in your SQL Server which has millions of rows in it and for whatever reason you decide you want to delete all of them. So, you initially think "simple, I'll just do this":

delete from [MyTable]

But there's a problem with this. You see, you are also using a full recovery model and are therefore writing to a transaction log file for every transaction you perform. If you were to send this command to SQL Server, it has to also write millions of updates to the transaction log in case you need to recover this data. If this also happens to be your live database you've now effectively brought it grinding to a halt. Not good.

So, the way around this problem is actually quite simple. Instead of deleting millions of rows at once, delete much smaller batches of rows but keep doing it until the table is empty.

declare @rows int = (select COUNT(*) from [MyTable])

while @rows > 0 begin
    delete top (10000) from [MyTable]

    set @rows = (select COUNT(*) from [MyTable]
end

Deleting 10,000 rows at a time will not make much of a dent when updating the transaction log and, because we keep repeating the operation when each delete is finished, other connections to the database can still do work, meaning you can now do this in a live environment and not affect performance much - though I would hope you know what you are doing clearing that big a table in a live environment!