Converting Your ASP.NET Web Forms Application to ASP.NET MVC

If you want to build a Web application quickly, do it with ASP.NET Web Forms. However, you have to be willing to give up a lot: client-side coding and Ajax is more awkward in Web Forms than MVC, you won't have as complete control over your HTML/CSS as in MVC, and you'll have to be careful about what code goes into your code-behind file if you want to do automated testing.

Because those are areas that people do care about, the future of Web development in .NET belongs to ASP.NET MVC (it's telling that there is no "MVC" in .NET Core -- the Web application framework is just called "ASP.NET Core").

I made a good living out of Web Forms, but, except for the occasional fix to legacy applications, my clients all want me to work in ASP.NET MVC now. That being the case, I occasionally get asked "How do I migrate from Web Forms to MVC?" Here's what I tell my clients (and I won't charge you a thing):

  1. Don't. There is no migration path and your Web Forms application has that whole "working" feature that users like.
  2. If it's just a need to add client-side support or to look up-to-date, consider replacing the default Microsoft Web Form controls with controls from third-party providers. A lot of those third-party controls offer features that the default Microsoft Web Form controls don't (rich client-side models, for example). They are also often "plug-compatible" with your current controls so you can just replace your existing Microsoft control with a third-party control and start doing cool stuff.
  3. If you must convert (because you don't want to support two toolsets or there's something you want your application to do that Web Forms doesn't support or your commercial application looks old fashioned or management has mandated it or ...), remember that, since Visual Studio 2012, you can combine MVC and Web Forms in the same project. Do the conversion form by form rather than creating a whole new site. There will be some forms (those forms maintaining your lookup tables, for example) that you may never bother converting.
  4. Where you need to rewrite an existing Web Form to ASP.NET MVC, remember that you wrote that form the way you did because you wrote it in Web Forms. If you'd written it in MVC, you'd have done it differently. Do it that "differently way" now.
  5. Do create all your new pages in ASP.NET MVC even in existing Web Form projects (no sense in making the problem larger).

Posted by Peter Vogel on 03/12/2018 at 8:45 AM0 comments


Brush Up Your SQL

Thanks to LINQ and Entity Framework, I don't write a lot of online, transactional SQL any more (I like to think that, thanks to Entity Framework, I have Microsoft's ADO.NET team doing that for me). But there are features in SQL that just aren't available in the current version of LINQ (see my columns on SQL Server 2016's support for JSON and temporal tables for examples).

But it isn't just new features that may drive you to issuing raw SQL through Entity Framework, though.

For example, I had someone attending one of the SQL Server querying classes I teach with a problem that LINQ couldn't solve efficiently (I also teach the 2014 course, though it doesn't really matter because they're exactly the same course ... though, as I remember, the 2016 certification exam was easier).

His problem was that he was receiving a constant stream of reports from various vehicles and needed, from that received data to determine when the vehicle had stopped to refuel. The only way to answer this question is to compare the amount of gas in the tank at (time A) with the amount in the tank at (time A – 5 minutes).

In LINQ, this could be solved by joining every report row with all the report row from the same vehicle more than 5 minutes ago ... but that query had a response time that could be measured with a calendar, not with a stop watch. However, a raw SQL query that used the Preceding keyword (not available in LINQ), gave a very snappy response.

I love LINQ. I love Entity Framework. You're still going to need SQL.

Posted by Peter Vogel on 03/05/2018 at 7:20 AM0 comments


Avoiding Entity Framework Slowdown

Generally speaking, I don't worry much about tweaking my LINQ queries when working with Entity Framework (this is also true when I'm working with SQL directly, by the way). I'm always telling my clients that if they want to speed up their data access they should look at their database design and, especially, how they're using indexes.

There is one exception to that rule, though: If you've got a query doing a comparison to a char or varchar column, then you may be unnecessarily slowing down your LINQ queries. The problem is that Entity Framework assumes that the database equivalent to your string property is a Unicode (nchar or nvarchar) column. If that's not the case -- if your columns are char or varchar -- then you're incurring some data conversion overhead when you use those properties in a Where clause like this:

Dim res = From cust In db.Customers
 	   Where cust.Name = "Vogel"
	   Select cust

That Where clause is going to get converted into a SQL statement that looks like this:

Select *
From Customers
Where Name = N'Vogel'

Because Entity Framework assumes my column is a Unicode column, it slaps the N in front of my string constant ('Vogel') to turn it into a Unicode literal ... and then tries to compare that Unicode literal to my non-Unicode (char or varchar) Name column. SQL Server then has to do the work to convert 'Vogel' back out of Unicode (or it may be converting my Name column to Unicode, either of which is bad).

The solution is to tell Entity Framework that your column is char or varchar by decorating the property with the Column attribute and setting the attribute's TypeName property. This example tells Entity Framework that my Name column is varchar:

<Column(TypeName="varchar")>
Public Property Name As String

For a longer discussion, see Brian Sullivan's blog post on how he got burned. And stop using char and varchar!

Posted by Peter Vogel on 02/23/2018 at 8:59 AM0 comments


The C# Scopes for Privileged Inheritance

You can't really combine the various scopes that you can apply to a C# member because, I suspect, they wouldn't make sense (what's the scope of a public private method, for example?). However, you can combine internal with private and protected like this:

public class CustomerBase
{
  protected internal void DeleteCustomer() {

or

public class CustomerBase
{
  private protected void DeleteCustomer() {

In my first example, because of its internal scope, DeleteCustomer can be used by code that instantiates CustomerBase but only if that code is in the same project as CustomerBase. Because of the protected declaration, however, code in other projects can access DeleteCustomer through a class that inherits from CustomerBase.

Code in other projects that instantiate CustomerBase directly won't see DeleteCustomer. Essentially, code in the same project as CustomerBase has a privilege denied to code in other projects (the ability to delete customers, in this case).

The scope private protected goes even further and is probably more useful. This scope prevents DeleteCustomer from being accessed except through classes that derive from CustomerBase and only if those derived classes are in the same project as CustomerBase.

Code in some other project in a class that inherits from CustomerBase won't be able to access DeleteCustomer. This allows you to create derived classes in the same project as CustomerBase that have privileges denied to classes in other projects that inherit from CustomerBase.

Posted by Peter Vogel on 02/21/2018 at 6:47 AM0 comments


Getting Data from the Request Object in ASP.NET MVC

Most of the time in ASP.NET MVC I can count on model binding to fill in the values for the parameters to my Action methods. Every once in a while, though, model binding doesn't do what I expect. You can create your own custom modelbinder to solve this problem (I've even discussed how to do that for the ASP.NET Web API). However, that may be overkill.

Often you can solve your problem by accessing one (or all) of the collections in ASP.NET's Request object (available in your controller through its Request property). There are a number of collections you can use to access data sent from the browser and their names do a pretty good job of describing what data they hold:

  • Cookies
  • Files
  • Form
  • Headers
  • QueryString
  • ServerVariables

You can also use the Params collection (which combines the values from Cookies, Form, QueryString, and ServerVariables) but you'd be safer with one of the more specific collections. The problem with the Params collection is that you can have the same data stored under the same name in multiple collections (Cookies and QueryString, for example). If you use Params you can't be sure which of those collections your data will come from.

Posted by Peter Vogel on 02/20/2018 at 5:52 AM0 comments


Paste JSON and XML as a Class

I don't use Visual Studio's Edit menu enough, obviously: For some time there's been a Paste Special option on that menu that I didn't know about. It has up to two choices depending on what kind of file you're editing: Paste XML as Classes and Paste JSON as Classes. Using the Paste JSON as Classes option, I can copy some JSON in my JavaScript code and create a corresponding C# or Visual Basic class in my server-side code just by picking a menu the appropriate menu choice.

However, I'd rather be able to use this functionality without having to drag my mouse to the Edit menu. To support that, I added a keystroke combination for the underlying commands related to these menu choices.

If you want to do the same, first go to Tools | Options | Environment | Keyboard. To grab the commands, in the "Show commands containing" textbox, type in AsClasses and select one. Then, from the "Use new shortcut in" dropdown list, pick your language's editor (for example, CSharp Editor or Microsoft Visual Basic Editor). Now you can click in the "Press shortcut keys" textbox to select your shortcut key(s): Just press the keys you want to use. Finally, click the Assign button. Lots of people forget that step and just click the OK button at the bottom of the dialog (by "lots of people" I mean: me).

You probably don't want to override any existing shortcut keys so I'd recommend picking a "chord": two or more keys pressed sequentially while holding down one of the control keys (the dialog box will tell you if you pick a shortcut that's already in use). I picked Ctrl+K, J for pasting JSON and Ctrl+K, M for pasting XML (Ctrl+K, X was already taken for inserting snippets and, who knows, I might start using that some day).

My life would be complete if there was a Paste Class as JSON when I was in a TypeScript or JavaScript file. In the meantime, I'm settling for Edit | Insert File as Text and doing some editing or using Nha Bui Doc's TypeScriptSyntaxPaste.

Posted by Peter Vogel on 02/16/2018 at 6:16 AM0 comments


Manipulating URLs on the Server

There's nothing stopping you from working with URLs in code using standard string functions. If you want to create a URL, you should use the URL object. On the other hand, if you want to analyze a URL -- or, more properly, a URI -- you should use the Uri class.

To use the Uri class, you just instantiate it, passing a URI. Once you've done that, you can check whether the URI's scheme name (ftp, http and so on) is valid, that the host name is a valid DNS name, or even dismantle the URI to get its individual components (to get, for example, the port or host name).

You can even use the Uri object to compare two URLs to see if they are significantly different (the Uri object is smart enough to recognize that two URLs are identical if one URL omits a port number while the other one specifies the default).

Posted by Peter Vogel on 02/13/2018 at 10:27 AM0 comments


Best Practice: Declare Variables as Constants

In the bad old days, I only used constants as a way to assign names to values. Things like this, for example:

Private Const DaysInWeek As Integer = 7

However, these days most of my variables are holding objects; Some of my other variables are holding things like collections or delegates. That changes what we mean by "constant."

When a variable is declared as a constant, it doesn't mean that the object it's holding is immutable. You can, for example, still change values in the properties of an object held in a constant or add items to a collection held in a constant. It just means that you can't replace the object (or collection) that was assigned when the variable was initialized.

Especially in TypeScript (where many of my variables are holding functions), I'm switching to declaring my variables as constants. A subset of these variables are fields (class-level variables) that are set precisely once, in an object's constructor, and I'm taking the time to mark as those read only also.

If I want an actual immutable object I'll declare the object's properties as read only or use one of .NET's read only collections.

In part, I'm doing this because I'm thinking more in terms of value objects (an important concept in Domain Driven Design). However, there are other benefits. I'm told, for example, it makes life easier for the compiler. But it's also because this practice sends a clear message to the next developer (either using my code or modifying it) about how I think that the object should be used.

Posted by Peter Vogel on 02/12/2018 at 7:20 AM0 comments


Pasting Into a Command Window

I amazed a client recently who was looking over my shoulder when I copied a file path from the address in Windows Explorer.

Actually, it wasn't copying the path that impressed him -- it was when I pasted that text into a command window. I clicked in the command window, clicked on the icon at the right-hand end of the command window's title bar and, from the dropdown menu, selected Edit | Paste.

As the file path appeared in the window, he said "Now, that's cool."

This is how you get a reputation as wizard, kids. (I didn't say it was hard to do.)

Posted by Peter Vogel on 02/09/2018 at 6:20 AM0 comments


Load TypeScript Modules as You Need Them

In the bad old days you put all your JavaScript code into a single file and loaded that file on every page that needed any of your code. As the amount of JavaScript code increased, you started organizing your code into files and loading just the files you needed.

Currently, you can organize your code into modules and, for any particular module, specify what other modules it needs. Using a module loader, those other modules will automatically be loaded for you.

In the current version of TypeScript you can now load a module only if you actually need it. If you have a section of code that isn't always executed but requires some additional module support when it is used, then you can load that support dynamically at run time.

All you need to use is the import method, passing the relative path name to the file containing the module you need.

Of course, it will take a while for that file to be fetched and the module it contains made available. To handle that you can use the async and await keywords to make sure that you don't use that support until it's ready.

Typical code might look like this:

async function doSomethingAdHoc(): Promise<void> {
  if (userRequestedASpecialFunction) {
   await import('...relative path to JavaScript file...');
   ...do something...
  }
}

Posted by Peter Vogel on 02/08/2018 at 6:34 AM0 comments


Check That Your Config Files Are Transformed Correctly

Having a process to manage the settings in your application's Web.config file as you move from release to production is essential to ensuring your production Web site works correctly.

One way to handle that is to set up a Web.release.config file with transformation rules to convert your development config file to your production version whenever you compile in Release mode.

In Visual Studio, you can check to see if that transformation is doing what you want by right-clicking on the Web.release.config file in Solution Explorer and then selecting Preview Transformation from the popup menu. Selecting Preview Transformation will open a window with two panes; the pane on the left shows your original file, while the pane on the right shows your transformed version.

Any lines that are modified, added or deleted are automatically highlighted in both panes, making it easy to see what changes will be made. You don't even have to go looking for the changes, either: There's a bar down the right side of the window, flagging where in your config file you'll find your changed lines.

Do be careful, though: It's possible to write your transformation so it doesn't find the part of your config file it's supposed to transform and, as a result, no transformation is made. Other than the absence of a change (something that's hard to notice), there's nothing in the preview to flag that your transformation has failed.

Posted by Peter Vogel on 01/05/2018 at 10:04 AM0 comments


Get Back to the Visual Studio Editor Window Without the Mouse

So your mouse is in some tool pane in Visual Studio and you want to get back to the editor window. You don't have to reach for the mouse -- just press the Escape key. You may have to press the key multiple times but sooner or later, your cursor will probably end up in the editor window. I have to say "probably" because, every once in a while, using Escape won't get you back to the editor window.

To make up for that uncertainty, here's another tip: Once you're back in the editor window, if the current document isn't the one you want, you still don't have to reach for the mouse -- just press Ctrl+F6 to cycle through the currently open documents.

Posted by Peter Vogel on 11/18/2016 at 12:33 PM0 comments


Most   Popular
Upcoming Events

.NET Insight

Sign up for our newsletter.

Terms and Privacy Policy consent

I agree to this site's Privacy Policy.