Posted by John Lockwood on August 31st, 2009
This is a reprint of a review I did on Amazon.com.
I bought Stephen Walther’s ASP.NET MVC Framework Unleashed after several months of working on a legacy C and C++ project which looks nothing like Walther’s book. Following that I spent many a happy Saturday and Sunday ramping up on Ruby on Rails, but finally giving up to revisit my Microsoft skills. ASP.NET MVC is a serious attempt by Microsoft to lure wayward Ruby on Rails types like me back into the fold, and I consider myself re-folded.
Given my background, any halfway decent book on ASP.NET MVC would probably have been welcome, but Walther’s book is especially welcome because it makes a serious attempt to treat ASP.NET MVC in the context of Test Driven Development. Well, all of that is what you’d expect if you take the cynical view that Microsoft is competing for developer mind share against Ruby on Rails, where the tests are "baked right in" (of course they all pass by default, but that’s another story). But Walther’s book is far more than a cheerleading book about TDD, and actually gets you into how to structure your code to support it. Using a generic repository class and relying heavily on the dependency injection pattern, Walther leads you through setting up your code so that it’s loosely coupled, testable, and (presumably) easily refactored.
Admittedly, it sometimes looks like Walther’s approach takes too much manual lifting compared to Ruby on Rails — and that’s especially true when you run into Microsoft annoyances like not being able to refresh an Entity Data Model from the database. On the other hand, it’s hard for an experienced software developer not to take a skeptical view of the magical rails "we can build a blog in 15 minutes" approach to the world. But still I feel that the techniques Walther talks about are the kind of thing that I really need to try out on an application or two.
I gave the book four stars because there were a few sections that I thought could have been explained better. For example, I used his chapter on deployment almost immediately to create an application that supports both "legacy" ASP.NET and ASP.NET MVC, and the information there worked great, but I felt the file differences could have been narrowed down a bit more. Also in his discussion of the generic repository, I felt like we lost sight of the model there for awhile. Since there was a lot of ground to cover, a general overview discussing how the Entity Data Framework, the model, the repository and the service layer were all going to tie together might have been helpful. My final quibble is that I felt there could have been a bit more material on the relationships among the Entity Data Framework, LINQ, and LINQ to SQL. I think Walther’s book gave the impression that the EDF and LINQ are orthogonal, whereas other Microsoft sources lead me to believe they’re more complimentary.
Despite its flaws, however, I want to leave you with the title of my review, that this is one of the best programming books I’ve read in a long time. It’s the kind of book that expands your horizons and makes you want to try things out the way the author has outlined. To be sure, Walther’s book is not the book you want to read if you goal is to hack together an unstructured ASP.NET MVC application in record time. But if your goal is to learn ASP.NET MVC while becoming a better programmer along the way, this book merits your serious attention and you should be pulling your credit card out now.
Posted in ASP.NET, ASP.NET MVC | 1 Comment »
Posted by John Lockwood on August 30th, 2009
-
Embed configuration management functionality into a .NET Framework application.
May include but is not limited to: Configuration class and ConfigurationManager class; ConfigurationSettings class, ConfigurationElement class, ConfigurationElementCollection class and ConfigurationElementProperty class; Implement IConfigurationSectionHandler interface; ConfigurationSection class, ConfigurationSectionCollection class, ConfigurationSectionGroup class and ConfigurationSectionGroupCollection class; Implement ISettingsProviderService interface; Implement IApplicationSettingsProvider interface; ConfigurationValidationBase class; Implement IConfigurationSystem interface
-
Create a custom Microsoft Windows Installer for .NET components by using the System.Configuration.Install namespace, and configure .NET Framework applications by using configuration files, environment variables, and the .NET Framework Configuration tool (Mscorcfg.msc).
May include but is not limited to: Installer class; Configure which runtime version a .NET Framework application should use; Configure where the runtime should search for an assembly; Configure the location of an assembly and which version of the assembly to use; Direct the runtime to use the DEVPATH environment variable when searching for assemblies; AssemblyInstaller class; ComponentInstaller class; Configure a .NET Framework application by using the .NET Framework Configuration tool (Mscorcfg.msc); ManagedInstallerClass; InstallContext class; InstallerCollection class; Implement IManagedInstaller interface; InstallEventHandler delegate; Configure concurrent garbage collection; Register remote objects by using configuration files
-
Manage an event log by using the System.Diagnostics namespace.
May include but is not limited to: Write to an event log; Read from an event log; Create a new event log
-
Manage system processes and monitor the performance of a .NET application by using the diagnostics functionality of the .NET Framework.
May include but is not limited to: Get a list of all running processes; Retrieve information about the current process; Get a list of all modules loaded by a process; PerformanceCounter class, PerformanceCounterCategory and CounterCreationData class; Start a process both by using and by not using command-line arguments; StackTrace class; StackFrame class
-
Debug and trace a .NET Framework application by using the System.Diagnostics namespace.
May include but is not limited to: Debug class; Debugger class; Trace class, CorrelationManager class; TraceListener class; TraceSource class; TraceSwitch class; XmlWriterTraceListener class; DelimitedListTraceListener class and EventlogTraceListener class; Debugger attributes
-
Embed management information and events into a .NET Framework application.
May include but is not limited to: Retrieve a collection of Management objects by using the ManagementObjectSearcher class and its derived classes; ManagementQuery class; Subscribe to management events by using the ManagementEventWatcher class
Posted in Configuration, Diagnostic, Management, and Installation features | 1 Comment »
Posted by John Lockwood on August 28th, 2009
In .NET, delegates are classes that implement type safe function pointers. Like all function pointers, they can be used whereever you need dynamic execution of code. One use of delegates that is ubiquitous in .NET is as a mechanism for handling events. Both ASP.NET Webforms and the Windows development Winforms classes uses such delegates as event handlers. So does our little program below, which shows how to translate keypresses into events, then handle certain events as they’re raised.
As a side note, this was the first sample I developed using Visual Studio 2010 beta (though it compiles and runs fine under 2005 as well).
Output of course varies depending on what keys you press. One possibility:
[[code]]czoyMTM6XCIKYVByZXNzZWQ6ICBhCmJQcmVzc2VkOiAgYgrimLtQcmVzc2VkOiAg4pi7CkNvbnRyb2wga2V5IHByZXNzZWQK4peEUHJ7WyYqJl19ZXNzZWQ6ICDil4QKQ29udHJvbCBrZXkgcHJlc3NlZArimaZQcmVzc2VkOiAg4pmmCkNvbnRyb2wga2V5IHByZXNzZWQKYVByZXNzZXtbJiomXX1kOiAgYQpBbHQga2V5IHByZXNzZWQKIFByZXNzZWQ6CkFsdCBrZXkgcHJlc3NlZApDb250cm9sIGtleSBwcmVzc2VkClwiO3tbJiomXX0=[[/code]]
Posted in Developing Applications That Use System Types and Collections | 1 Comment »
Posted by John Lockwood on August 26th, 2009
-
Implement, install, and control a service.
May include but is not limited to: Inherit from ServiceBase class; ServiceController class and ServiceControllerPermission class; ServiceInstaller and ServiceProcessInstaller class; SessionChangeDescription structure and SessionChangeReason enumeration
-
Develop multithreaded .NET applications.
May include but is not limited to: Thread class; ThreadPool class; ThreadStart delegate, ParameterizedThreadStart delegate, and SynchronizationContext class; Timeout class, Timer class, TimerCallback delegate, WaitCallback delegate, WaitHandle class, and WaitOrTimerCallback delegate; ThreadExceptionEventArgs class and ThreadExceptionEventHanlder class; ThreadState enumeration and ThreadPriority enumeration; ReaderWriterLock class; AutoResetEvent class and ManualResetEvent class; IAsyncResult interface and ICancelableAsyncResult interface (refer System Namespace); EventWaitHandle class, RegisterWaitHandle class, SendOrPostCallback delegate and IOCompletionCallback delegate; Interlocked class, NativeOverlapped structure and Overlapped class; ExecutionContext class, HostExecutionContext class, HostExecutionContextManager class, and ContextCallback delegate; LockCookie structure, Monitor class, Mutex class, and Semaphore class
-
Create a unit of isolation for common language runtime within a .NET Framework application by using application domains.
May include but is not limited to: Create an application domain; Unload an application domain; Configure an application domain; Retrieve setup information from an application domain; Load assemblies into an application domain
Posted in Implementing service processes, threading, and application domains in a .NET Framework application | 1 Comment »
Posted by John Lockwood on August 24th, 2009
Note that the example below has no output.
<pre>/*
* This example shows a non-generic list with an array of objects,
* and the boxing and unboxing that are needed to add and retrieve integers
* from such an array. It also shows a generic list and how this simplifies
* access to a value type such as int.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
class ListsExample
{
public void CreateNonGenericList()
{
ArrayList list = new ArrayList();
// Boxing
Object o1 = (Object)1;
// Boxing again
Object o2 = 2.ToString();
list.Add(o1);
list.Add(o2);
// Add myself
list.Add(this);
// Have to unbox (or cast) to get explicit type out
// Run time exception if get it wrong.
// Unbox
int i = (int)list[0];
// Unbox
string s = (string)list[1];
// Cast
ListsExample myclass = (ListsExample) list[2];
}
public void CreateGenericList()
{
List<int> list = new List<int>(10);
for (int i = 0; i < 10; i++)
{
list.Add(i);
}
// Can access any variable directly as an int without casting
int four = list[5];
}
static void Main(string[] args)
{
ListsExample lists = new ListsExample();
lists.CreateGenericList();
lists.CreateNonGenericList();
}
}</pre>
Posted in Developing Applications That Use System Types and Collections | 1 Comment »
Posted by John Lockwood on August 22nd, 2009
Value types include:
- Simple types such as numeric types (int, long, float, decimal) and bool (Full List)
- Enumerations
- User defined structs .
All value types are derived from System.ValueType.
As the name suggests, value types directly contain values. The values are stored on the stack, i.e.:
int i = 1;
Value types generally cannot contain null values, with the exception of Nullable types.
Because value types directly contain values, assigning a value type makes a copy of the value. In contrast, assigning a reference type to a new variable makes a new reference pointing to the original type.
using System;
// A really simple Reference class for testing --
// wrap an int.
class ReferenceTest
{
private int val;
public int Val
{
get
{
return val;
}
set
{
val = value;
}
}
public override string ToString()
{
return val.ToString();
}
};
class ValueVersusReference
{
static void Main()
{
ReferenceTest ref1, ref2;
ref1 = new ReferenceTest();
ref1.Val = 42;
// ref2 points to same memory as ref1
ref2 = ref1;
// therefore changing ref1 will be reflected in ref2
ref1.Val = 52;
Console.WriteLine("ref1 = {0}\nref2 = {1}", ref1, ref2);
int val1, val2;
val1 = 42;
// val2 is a copy of val1
val2 = val1;
// changing val1 has no effect on val2
val1 = 52;
Console.WriteLine("val1 = {0}\nval2 = {1}", val1, val2);
}
}
This code outputs:
<pre>ref1 = 52
ref2 = 52
val1 = 52
val2 = 42</pre>
Posted in Developing Applications That Use System Types and Collections | 1 Comment »