Posts Tagged 'Visual Basic'

Validating That At Least One TextBox Has Content

I came across an interesting little validation problem on my current project. The site is for members only – and in order to become a member, you need to be nominated. You can provide either one or two nominators, but you must provide at least one.

So how to force users to enter text in either of two TextBoxes? RequiredFieldValidators won’t do, because either one can be left empty. Yet at least one must be completed. Clearly this is a job for CustomValidators.

The client-side and server-side code are both fairly straight-forward, but I thought someone out there might find it useful, so here it is.

First of all, the CustomValidators in the ASPX page:


<asp:CustomValidator ID=”Nomination1CustomValidator” runat=”server” Display=”None” ValidateEmptyText=”true” ClientValidationFunction=”CheckNominations” ErrorMessage=”At least one nomination must be provided” ControlToValidate=”Nominated1TextBox” OnServerValidate=”Nomination2CustomValidator_ServerValidate”></asp:CustomValidator>


<asp:CustomValidator ID=”Nomination2CustomValidator” runat=”server” Display=”None” ValidateEmptyText=”true” ClientValidationFunction=”CheckNominations” ErrorMessage=”” ControlToValidate=”Nominated2TextBox” OnServerValidate=”Nomination2CustomValidator_ServerValidate”></asp:CustomValidator>

Note the empty ErrorMessage in the second validator. Combined with display=”none’, that means our ValidationSummary control is only going to display one error message to the user, making it much less confusing. Also notice that ValidateEmptyText is set to true – otherwise, our code will never run.

Then the JavaScript. We’re validating two controls, so even though we use the standard signature the validators are expecting, we’re only interested in the args. I set the TextBoxes’ ClientIDMode to static and used jQuery to get the controls.  (I use jQuery for pretty much all my client-side code).

function CheckNominations(sender, args) {
  if ($(‘#Nominated1TextBox’).val() == “”
      && $(‘#Nominated2TextBox’).val() == “”) {
        args.IsValid = false;
  }
   else {
args.IsValid = true;

   }

}

And, of course, we also need to implement the server-side code for a complete solution:

If String.IsNullOrEmpty(Me.Nominated1TextBox.Text) And
String.IsNullOrEmpty(Me.Nominated2TextBox.Text) Then
        args.IsValid = False
Else
        args.IsValid = True
End If

So now the user must fill in one of the TextBoxes, but can pick either one.  I have been using ASP.NET MVC a lot recently, and it’s nice to go back to Web Forms and see how very easy it is to take built-in controls like the custom validator and use them to meet your specific needs.

Kevin Rattan

For related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET and Ajax

jQuery: A Comprehensive Hands-On Introduction

Unit Testing ASP.NET MVC with MvcContrib

One of the big drivers for people moving over to ASP.NET MVC is its support for Test Driven Development/Unit Testing. The ability to automate testing of models and controllers brings a measurable level of confidence to development. In ASP.NET MVC, that means we can be sure that we are getting the expected views, data and routes from our controllers.

Unless they do something that only works in a Web context, in which case we get an exception.

The problem is that the Visual Studio Test Framework isn’t a Web client. The moment your controller does something that only works in a Web context, like accessing a session variable, your test will break with a NullReferenceException.

Screenshot of NullReferenceException

The controller in the test project has a Session property – but if you try and set Session variables, you will simply move the NullReferenceException up one level into your test project. That’s where MvcContrib comes in. It’s an open source project available at CodePlex, and it allows you to mock up the HttpContext and populate the Session etc. with the values your methods require.

Once you’ve downloaded MvcContrib, you need to set a reference to it inside your test project. The classes you want are inside the TestHelper namespace, so add it as an Imports. Then get the TestControllerBuilder to create the controller for you – that will give you the extra framework you need to add in the HttpContext elements. The easiest thing to do is add a controller variable at the class level, and then call CreateController() inside a TestInitialise() method.

code sample creating controller

The TestControllerBuilder gives you a more fully featured version of the controller. Now, if you set a Session variable, the value will be passed through to the controller and you won’t get the NullReferenceException in either the test project or the controller.

code sample setting Session variable in test code

So now you can run your tests and have them pass – even when your code has elements that require a HttpContext.

screenshot successful tests

One gotcha to watch out for. You need to have a mocking framework available – so make sure that you also reference one of the mocking frameworks that works with TestHelper or you’ll get an exception when you try to run your tests. In the sample above, I referenced Rhino.Mocks, which is included with MvcContrib.

MvcContrib has quite a lot of other features beyond testing, and I might well come back to some of those in later posts.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

.NET Best Practices and Design Patterns: Hands On

Preventing Duplicate Logins in ASP.NET

ASP.NET provides a convenient and highly extensible authentication and authorization system that is shared by both ASP.NET MVC and ASP.NET Web Forms. I have cheerfully used it for years, without ever worrying about the fact that there is nothing in the system to prevent the same user from logging in multiple times. The other day, though, I received an email from a former student who was concerned about just that. Their business rules had changed, and now they needed the following behavior: if a user logs on twice with the same identity, the first user should be automatically logged out.

It was not something I had ever thought about before, and I became intrigued. I could imagine preventing the second user from logging in – but how to allow the second login to go through, and bounce the first user from the site? The idea intrigued me so much, I decided to put together a little test site.

I created a standard ASP.NET MVC3 Web application.

I then added code to the LogOn action method:

(The reason for the Session (“fixer”) is that if nothing is in the session, the ID can change between requests – and we’re relying on it staying the same).

Now that we have saved the sessionID of the current user (and overwritten any existing value), we can test for it on every request – and bounce out any user who doesn’t have the current one. In ASP.NET MVC, this is best done using an action filter. Here is the code for the LogUserOut action filter:

Now all we need to do is create an action method and View for Bounce, and assign the LogUserOut attribute to the appropriate action methods – in this case, Index and About:

Then I tested it. I logged on in Internet Explorer, created a new user and had no problem clicking Home and About.

Then I opened Firefox and logged in as the same user. Again, this was no problem and everything worked as it should.

Then I went back and clicked on a link in IE – and was bounced out: exactly what was supposed to happen.

So I logged in again in using IE.. and then went back to Firefox, where the current user was once again bounced out.

So the principle works. I wasn’t that happy with the solution, though. The use of the UserName is less than optimum – what if two users had the same name? So I reworked it to use ProviderUserKey as the cache key. That added a little complexity, as the MembershipUser is not available inside the LogOn action. To get around the problem, I redirected to a new Welcome action after a successful login, and used that to add the user to the cache. I had to do a bit of work to ensure the returnUrl was still honored and that unauthenticated users didn’t hit the Welcome method and cause issues, but it was a better solution as a result. (In Web Forms, I would have used the LoggedIn event to access the MembershipUser. I would also have inherited from a base page to provide the bounce logic, rather than using an action filter.) Another possible change would be to use a database instead of the cache, which would be slower but more reliable in a Web farm.

If you’re interested in the code for the complete solution, then you can download it from here. If you want to find out more about ASP.NET MVC, you might want to check out Building Web Applications with ASP.NET MVC. If you’re interested I learning more about security and state management in Web Forms, then I’d recommend Building Web Applications with ASP.NET and Ajax (of which I’m the author).

Kevin Rattan

Which .NET CMS to Use?

The question for today is – if I’m planning on implementing an ASP.NET Web CMS, which one should I choose?

My company used to have its own custom .NET Web CMS, Mantranet. Mantranet was a good solution in its day – it was end-to-end AAA accessible, for one thing – but eventually it became a little long in the tooth and we felt it was no longer worth the effort to modernize the product. The CMS market is now so crowded, and has major players like SharePoint in the field. We decided it was time to move on.

So the question became – which .NET CMS was the right one for us?

We could have gone with SharePoint, of course, but having looked at it, we didn’t feel it was really appropriate for us. SharePoint is very popular, and it’s great for managing information within a large company, but not so much for creating self-standing Web sites (at least, not if you are working with the free version).

So, if not SharePoint, who? The two obvious choices are DotNetNuke and Orchard. With Microsoft putting such a big push behind ASP.NET MVC, and with some Microsoft developers working on the open source Orchard ASP.NET MVC CMS, it seemed like a good idea to give it a try.

orchard home page

Orchard is a thing of beauty. It uses all the right architectures, from Inversion of Control to Test Driven Development. It has extensibility built into it at every point. It uses the Razor view engine (with HTML5) and has clearly been designed by some top flight programmers. We played around with it, set up a test site and created our own theme.

screen shot of custom theme

Then we decided not to use it.

There are various problems. Firstly, Orchard is at such an early stage of development that it’s still buggy. I found that it would not successfully create a package for deployment, but gave no useful error message to show what the problem was. Any changes to the code, even trivial ones such as applying an attribute to require HTTPS for logging in, broke the application in unexpected ways. Themes provided on the Website had errors and broke when run in debug mode.

But much more important than any of these teething troubles is a fundamental design flaw: each page is conceived as a single, monolithic content element. Any additional content you want to add is going to appear on multiple pages.

I’ve also been developing DotNetNuke sites for a few years now. It isn’t perfect and it doesn’t have such a fancy architecture – but it works, and my customers can have as many content elements on a page as they like. (Just as they used to be able to do with Mantranet).

the huey091foundation website front page

So it’s a slam dunk – Orchard may be modern and pretty, but in terms of usability, DotNetNuke has it beat hands down. It’s easy to create your own modules (provided you know Visual Basic and ASP.NET), there’s a vibrant market in third party Modules and Skins and I’ve never had any problems with deployment. So my new site www.time2yak.com is a DNN site… We liked the look and feel of the Orchard version, though, so recreated the theme as a DotNetNuke skin.

Having said that, if you are interested in ASP.NET MVC, then I would strongly recommend downloading Orchard and taking a look at the code. It is seriously well done, and I learned a lot from it. I might well take another look the next time my company site needs renewing, and see if it hasn’t matured enough to be a real contender. Of course, it is very complex, and you might want (or even need!) to go on Building Web Applications with ASP.NET MVC first…

For related information, check out these courses from Learning Tree:
Programming SharePoint® 2010 Applications with .NET
Visual Basic® Programming for .NET
Building Web Applications with ASP.NET and Ajax

Kevin Rattan

Conditional Compilation

Have you ever been in a situation where your application needs to behave one way in development and another in production? Perhaps you only want to send an email if the application is on the live server, or you’re developing an ASP.NET MVC application and need to add the [RequireHttps] attribute – but only if the code is running on the production server.

It’s a different problem from changing connection strings between live and development versions. That’s easy – you just need different config settings for Release and Debug. (We show you how to do this in Building Web Applications with ASP.NET and Ajax). But how do you change behavior? The answer turns out to be surprisingly simple – by using conditional compilation.

The problem:

  1. Visual Studio does not include an SMTP server. If you try to run code that sends emails, you will get an exception – but not if you tell the system not to compile the send line unless you are in release mode.
  2. In ASP.NET MVC, the [RequireHttps] (VB: <RequireHttps>) attribute on a controller redirects a request from HTTP to HTTPS. The login Action method needs it if it is going to be secure – but it won’t work in Visual Studio. Unless, that is, you tell the compiler only to add the attribute in Release mode.

Here is the solution using C#:

#if !DEBUG

   [RequireHttps]

#endif

Now the attribute will only be added if the page is not being compiled in debug mode. To change between compilation modes, just change the selected configuration in the dropdown in the Visual Studio toolbar.

Exactly the same approach works with code as well as attributes – thus solving our email problem.

Here is the solution in VB:


Dim m As New MailMessage(Me.FromTextBox.Text, Me.ToTextBox.Text, Me.SubjectTextBox.Text, Me.BodyTextBox.Text)

Dim s As New SmtpClient(“localhost”)

#If Not Debug Then

     s.Send(m)

#End If

Conditional compilation is a simple technique that’s been around for a long time, but it remains enormously useful. Combined with different config files for different compilations, it allows you to customize your build to do just what it needs to do in a particular setup.

Kevin Rattan


Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 210 IT training and Management courses, including a full curriculum of .NET training courses.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 29 other followers

Follow Learning Tree on Twitter

Archives

Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

%d bloggers like this: