Properties with Parameters (and Making Them the Default)

Most developers aren't aware that you can write properties that accept parameters, just like a method does. Of course, it isn't often that you need a property that accepts a parameter. One way I recognize that I could use a property rather than a method is when my method name begins with the word "Get." Here, for example, is a method that (I assume) returns the specified part of a name:

Public Class NameManager
  Public Function GetNamePart(NamePosition As Integer) As String
    '...code
  End Function

If I rewrite the method as a property (and rename it), my class code looks like this:

Public Class NameManager
  Public ReadOnly Property NamePart(NamePosition As Integer) As String
    Get
      '...code
    End Get
  End Property

A developer who wants to get the customer's middle name would write code like this:

Dim nm As New NameManager("Peter Hunter Vogel")
Dim middleName As String
middleName = nm.NamePart(2)

You can go one step further and make this property the default property for the class, in which case a developer doesn't even have to use the property name. Here's the relevant code in Visual Basic (which adds the modifier Default to the property's signature):

Public Class NameManager
  Default Public ReadOnly Property NamePart(NamePosition As Integer) As String
    Get
      '...code
    End Get
  End Property

Here it is in C# (which renames the property to the keyword "this"):

public class NameManager
  public string this(int NamePosition) 
    get {
      '...code
   }

Regardless of how the class is written, the code to retrieve the middle name now looks like this:

middleName = nm(2)

Posted by Peter Vogel on 10/29/2015 at 3:12 PM0 comments


Why Won't My Razor Code Compile!?!

I've said it before: The Razor code that I enter into my ASP.NET MVC Views looks like magic to me. The ability Razor gives me to mix HTML and code surpasses my understanding. But, like magic, because I don't understand why Razor works, there are times where I don't understand why Razor doesn't work.

And neither do my clients, one of whom called me up last week to ask why code like the following wasn't acceptable to Razor (in C#, equivalent code wouldn't require the second @ ... but it still wouldn't compile):

@If RowRequired Then
  @<tr>
End If

The problem is that, inside a code block (like this If…Then block), Razor requires that all open tags have a matching close tag. Razor is fine with this code, for example:

@If RowRequired Then
  @<tr></tr>
End If

This can make structuring your HTML a little more awkward but, there is a solution: use @: instead of plain old @. With @:, this code compiles:

@If RowRequired Then
  @:<tr>
End If
</tr>

That's sharp!

Posted by Peter Vogel on 10/23/2015 at 1:16 PM0 comments


Catching Every Keystroke with jQuery

In an earlier column I used the jQuery change function to wire up a function to run after a user makes a change to an entry in a textbox. That "after" is important because the function I wired up won't run when the user makes a change in a textbox -- the event waits until the user leaves the textbox before firing.

In that article I mentioned, in passing, that if you really did want to catch a change as soon as a user makes it, you want to wire up the oninput event: The oninput event really does fire as soon as the user makes any change in a textbox. The major issue with oninput is that it's only available in browsers that support that portion of the HTML5 specification.

Unlike many other HTML events there's no built-in jQuery function to pick up the oninput event, so you need to use the jQuery on function to wire up a function to the event.

Here's some code that wires up a function that displays an alert box as soon as the user makes a change:

$(":text").on("input", function () { alert("got it"); });

You'll notice in my code that I'm using the :text selector, which only wires my function up to textboxes (it doesn't attach other input elements like passwords or checkboxes and also ignores dropdown lists and textareas). Several of the elements I'm skipping don't need the oninput event because the jQuery change event fires as soon as the user makes a change: Checkboxes and dropdown lists fall into that group. Password textboxes and textareas don't get caught by the :text selector, however, so you'll need to use more selectors to catch events immediately with them.

Posted by Peter Vogel on 10/13/2015 at 10:43 AM0 comments


Returning Server-Side Errors from AJAX Calls

In ASP.NET MVC if you call an action method on the server from JavaScript code and that action method raises an exception, you'll get an error at the client that lets you know something has gone wrong. Unfortunately, all the information you typically get is the HTTP 500 error status code and it's default message.

If you want to get your own custom error message delivered to the client, you could create your own custom error object and return it from the server when something goes wrong. Unfortunately, with that solution jQuery won't call the error function you specified in your $.ajax call -- you'll have to write your own code to check if the object returned from the server is your error object .

A better solution is to instantiate and return your own HttpStatusCodeResult, which does cause jQuery to call the error function you specify in your $.ajax call. This server-side code will do the trick, while providing a custom message to go down to the client:

return new HttpStatusCodeResult(410, "Unable to find customer.")

On the client, your message will be in the third parameter passed to your error function.

If you're handling multiple error conditions in the same action method and need to take different actions at the client depending on the error, you can give each error a different status code. If so, in your client code you'll need to check the error status code to see what error has triggered your error function. The error code is returned in the status property of the first parameter passed to your error method.

This client-side example calls a server-side method and, if the method returns a 410 error, displays my custom error message to the user:

$.ajax({url:'/home/deleteCustomer',
  data: {id: "A123"),
  success: function (result) {//handle successful execution},
  error: function (xhr, httpStatusMessage, customErrorMessage) {
    if (xhr.status === 410) {
      alert(customErrorMessage);}}});

Here's the list of defined HTTP status codes. If your message is suggesting that the error is something that the user can fix, then you should probably pick a code from the 400 series (that series is reserved for client errors). Personally, I don't think developers are using status code 418 ("I'm a teapot") enough.

Posted by Peter Vogel on 10/07/2015 at 11:28 AM0 comments


Display Just One Project in Solution Explorer

In a solution with many projects, typically you just want to work with one of the projects. You can, of course, collapse all of the projects you're not interested in, but (depending on how many projects you have) that can still leave a lot of lot clutter in Solution Explorer … and the project you're interested in half-way down the list. And the reality is that, from time to time, you're going to have to expand those other projects, which puts all that clutter back into Solution Explorer.

If, however, you right-click on the project you're mostly interested in and select Scope to This, Solution Explorer will switch Solution Explorer to a view that shows your project and nothing else. Now, when you need to get back to the full solutions listing, you just have to click the back button at the top of Solution Explorer. Back in the full version of Solution Explorer, you can return to your scoped, single project view by clicking the forward button right beside the back button.

This is a simpler solution than my previous tip on opening a separate Solution Explorer for individual projects. To begin, using Scope to This, you can only have a single project in a window by itself -- if you scope to another project you lose the scope on any other project. But, while opening multiple Solution explorers is more flexible I bet that, most of the time, scoping to one project is all the solution you need.

Posted by Peter Vogel on 09/29/2015 at 11:19 AM0 comments


Creating Your Own ASP.NET MVC Authorization Attribute

Applying role-based security is easy in ASP.NET MVC: Just decorate the relevant action method/controller class with the Authorization attribute, specify the allowed roles, and you're done. Every once in a while, though, I have a case where role-based security isn't enough.

For example, a client needed security to be applied differently depending on whether the current user was in the eastern or western division of the company. We could've duplicated all the roles in the company (EasternManager vs. WesternManager) or tried to find some clever way to combine roles (for example, assign users to an Eastern or Western role in addition to assigning them to the Manager role) and stack authorization attributes on each method. In the end I decided it was just as easy to create my own division-based Authorization attribute.

To create your own Authorization attribute you just need to create a class that inherits from AuthorizeAttribute and override its AuthorizeCore method. Your AuthorizeCore method must return True or False depending on whether you decide the user is accepted or rejected. This example rejects everyone:

Public Class DivisionAuthorization
  Inherits AuthorizeAttribute

  Protected Overrides Function AuthorizeCore(httpContext As HttpContextBase) As Boolean
    Return False
  End Function

End Class

If you want to send the user to a custom page of your own (rather than sending the Web server's default 404 page) you can also override the HandleUnauthorizeRequest method and use a redirect method inside the method to specify the controller/action method name that displays your rejection page.

One hint and one caveat before I'm done:

The hint: You can get ASP.NET MVC's opinion on whether the current user is authorized by calling the base AuthorizeCore method, and passing the same parameter that's passed to your AuthorizeCore method.

The caveat: Your AuthorizeCore method must be thread-safe, so you should only use local variables inside of it.

Posted by Peter Vogel on 09/24/2015 at 10:37 AM0 comments


Multiple Solution Explorers

If you've right-clicked on a project in Solution Explorer, you've probably noticed (but haven't used) the New Solution Explorer View choice. Clicking on that choice with a project selected in Solution Explorer opens a new Solution Explorer view that displays just that project. Initially, the new, dedicated view is free-floating but you can dock it anywhere you want, including docking it as a tab beside your "full" Solution Explorer view.

This is a great alternative to scrolling up and down between two projects in a solution: Once you've opened a view dedicated to a project and docked it, you can just click on the tab that displays the project with which you want to work.

There are two disappointments: You can't name the tab (so you end up with multiple tabs called "Solution Explorer"); Visual Studio doesn't remember your dedicated views from one editing session to another (it also drops any dedicated views if, for example, you add a new project to the solution).

You can actually open a new Solution Explorer view dedicated to almost any item in Solution Explorer, but I've only ever found it useful for projects.

Posted by Peter Vogel on 09/21/2015 at 10:56 AM0 comments


Convincing Razor to Recognize All of Your Expression

Razor's ability to distinguish between code and HTML/text often looks like magic to me. However, like any good magic act, I'm sometimes surprised by the results I get. For example, this code in a View didn't give me the results I expected:

@SalesOrder.CustomerName & " -- unknown"

Instead of getting the customer's name followed by " -- unknown", I got this:

Peter Vogel & " -- unknown"

Razor had decided that my expression ended at the space before my ampersand. Fortunately, to tell Razor where the real end of my expression is, I just have to include the whole expression in parentheses. This code solved my problem:

@(SalesOrder.CustomerName & " -- unknown")

Now I get:

	Peter Vogel – unknown

which is precisely what I want.

Posted by Peter Vogel on 09/14/2015 at 10:10 AM0 comments


Integrate Action Methods into ASP.NET MVC Partial Views

I find it handy to assemble complex Views from multiple simpler Partial Views. Sometimes, however, the result is a lot of code in my Views (I even did a column about managing that code). But there's another solution: The HtmlHelper's Action helper method, which allows you to call an action method and incorporate the results of that action method into your View.

This code in a View, for example, calls an action method named DisplayCustomer and adds the Partial View returned by DisplayCustomer to the View:

@Html.Action("DisplayCustomer")

My example is just the simplest way to call your action method -- you can also pass a controller name and an anonymous object with various property values.

Using the Action method lets you put much of your View-related logic where it belongs: in a method in your controller and not in your View (in the MVC design pattern, Views should have no logic at all). And, of course, once your logic is in a controller method, you can test it.

You probably don't want anyone invoking one of these action methods directly. You can tell ASP.NET MVC not to let that happen by decorating your action method with the ChildActionOnly attribute, like this:

<ChildActionOnly>
Function DisplayCustomer() As ActionResult
  Return PartialView("CustomerData")
End Function

Posted by Peter Vogel on 09/04/2015 at 10:34 AM0 comments


The Answer to Every File Path Related Problem

If you do anything at all with file path, you need the Path class (in the System.IO namespace). The methods on the Path class that you're most likely to use include:

  • GetTempFileName: Doesn't just return a filename that's guaranteed to be unique -- it also creates the file in the TEMP folder so you can start writing to it
  • GetFileName: Returns the file name from a path (and returns null if the path is just the path to a folder without a file name)
  • GetDirectoryName: Passed a file path, pulls out the full path to the folder without the closing backslash. One warning: this method returns null if passed the root folder ("c:\")
  • Combine: Puts a set of strings together to create a valid file path. Combine will add or remove backslashes as necessary, so the method will do the right thing with the path return by GetDirectoryName

These are the answers; any more questions?

Posted by Peter Vogel on 08/24/2015 at 10:18 AM0 comments


Finding Matching Brackets in C#

You can tell that the Visual Studio team recognizes the primary issue C# developers face: finding the matching bracket. That must be true because the most obvious way of finding "the other bracket" is built into the way code is displayed: When you put your cursor beside one bracket (open or close), both it and the matching bracket are highlighted (or, because the default color for the brackets is gray: lowlighted).

Unfortunately, that isn't much help if the "matching" bracket is off the screen: you can't see the highlighting if the bracket isn't visible. In those situations my fallback method used to be the plus/minus signs in the left hand margin of the editor window: I collapsed my C# methods to see what code disappeared and what code remained visible. The problem here, of course, is that the collapsed code was often the code in which I was interested.

There's a third option that not a lot of developers know about: Place your cursor on the bracket you're trying to match (open or close) and press Ctrl+] (that's the Control key with a closing square bracket). Your cursor moves to the matching bracket. Pressing the key combination again takes you back to the bracket on which you started.

There are other benefits: If you're bored and stuck on a problem, I've found repeatedly pressing Ctrl+] and watching the cursor snap back and forth can be soothing. And, if anyone is watching, it looks like you're working.

Posted by Peter Vogel on 08/19/2015 at 9:57 AM0 comments


Comparing Strings Without Worrying About Case

Developers frequently want to ensure two strings are identical without having to worry if some characters are in uppercase in one string and the same characters are in lowercase in the other string. Frequently, you see developers using either ToUpper or ToLower to avoid the problem:

If Name.ToUpper = OtherName.ToUpper Then...

But both ToUpper and ToLower create new strings, which is extra (and unnecessary) work.

If you can live with some extra typing, you can avoid generating those new strings by using the Equals method that every variable has, passing the InvariantCultureIgnoreCase choice from the StringComparison enumeration:

if (Name.Equals(OtherName, StringComparison.InvariantCultureIgnoreCase))

Now you have much less to worry about.

Posted by Peter Vogel on 08/12/2015 at 10:20 AM0 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.