Lazycoder

18Mar/093

ASP.NET MVC Tip – Return specific views for specific errors.

Earlier I had said to keep your controllers as thin as possible, that doesn't mean that they should necessarily just be two, or one, lines of code.

Take an instance where you are retrieving items from a web service in your controller. Let's say that you get a 404 error and your service will throw an exception telling you that the service can't be found. Take a look at this controller action

CODE:
  1. public ViewResult Item(string itemID)
  2. {
  3.     Item item = MyWebServiceWrapper.GetItem(itemID);
  4.     return View("Item", item);
  5. }

As it stands this action is pretty thin, but if an exception is thrown the user will be presented with either whatever custom error page you have defined in your web.config or the dreaded Yellow Screen of Death.(YSOD). You can wrap the call in a try-catch block and catch the exception. But rather than creating a generic errors page that will display any raw exception message, it's a much better idea to return an error specific view to your user with a friendly error message.

CODE:
  1. public ViewResult Item(string itemID)
  2. {
  3.     try
  4.     {
  5.         Item item = MyWebServiceWrapper.GetItem(itemID);
  6.         return View("Item", item);
  7.     }
  8.     catch(ServiceCannotBeReachedException)
  9.     {
  10.         Item item = new Item(itemID);
  11.         return View("CannotRetrieveItem", item);
  12.     }
  13. }
  14.  
  15. //The CannotReachService view has a line that looks like this
  16. // "The item <%= Model.itemID %> can not be retrieved at this time. Please try again later"
  17. // obviously this can be globalized/localized as needed.

This leads to a much "dumber" view and is a much better idea than modifying the "Item" view to display errors if something isn't right with the model or passing in special error parameters to the view. Let the view deal with the data it is meant to display and nothing else.

Filed under: .NET, MVC, Tutorials, Web 3 Comments
17Mar/096

ASP.NET MVC tip – Don’t use the Content or Scripts directories for view specific files

ASP.NET MVC creates a default file structure for you when you create a new project. It includes a Scripts directory, which contains the MS AJAX and jQuery .js files, and a content directory, which contains a Master page and CSS files. I find this to be extremely cumbersome and it forces me to jump around a lot. Storing shared CSS and JavaScript files in those locations is fine in my opinion. But if you are using View specific CSS or JavaScript files, you should put them alongside your view page in the Views directory. This allows you to quickly find the file you want to work on.

Filed under: .NET, MVC, Tutorials, Web 6 Comments
16Mar/0910

ASP.NET MVC TIP – Keep your controllers and actions thin

When writing you controller actions, keep them short and sweet. Don't add a lot of actions and keep a close eye on the length of each action.
Whenever possible, I try to make my controller actions look something like this.

CODE:
  1. public ActionResult DoSomething()
  2. {
  3.     MyModel model = MyService.GetModel();
  4.     return View("MyView",model);
  5. }
  6. //or
  7. public ActionResult DoSomethingWithAKey(int myKey)
  8. {
  9.     MyModel model = MyService.GetModel(myKey);
  10.     return View("MyView",model);
  11. }

(1)

There are two reasons to do this:

1) It makes your controllers less complicated and easier to maintain. - You don't want to have to do a lot of debugging in your controllers. Chances are, if you have a lot of complicated logic in your controller actions, you are probably mixing concerns. Make sure that your controllers are only responsible for getting data from your models and figuring out what view to send to the client.

2) It makes testing easier. If all you are doing is getting a model and passing that model to a view, what do you really need to test? Maybe that the correct view is being returned.

(1) Of course I use more descriptive names than "myKey". :P

Filed under: .NET, MVC, Tutorials, Web 10 Comments
23May/085

Modern JavaScript Development: Reflection in JavaScrpt

Sometimes you want to find out what members an object exposes. There's a pretty simple way to do this. A simple for-in statement.

CODE:
  1. for(var member in obj){ alert(member); };

No really, that's it. No "imports" or "using" statments. No complicated classes to memorize, no unwrapping or casting. Just for-in over an object. One caveat, this will show you ALL of the objects members and it doesn't distinguish between members declared directly on the objects and members inherited through the objects prototype. What if you just want to find the methods on an object? I've created two helper functions that will return just the methods(functions) of any JavaScript object.

CODE:
  1. Object.prototype.getAllMethods = function(){
  2. var memberArray = new Array();
  3. for (var method in this) {
  4. if (typeof this[method] == 'function') {
  5. memberArray.push(method);
  6. };
  7. };
  8. return memberArray;
  9. };
  10.  
  11. Object.prototype.getOwnMethods = function(){
  12. var memberArray = new Array();
  13. for (var method in this) {
  14. if (typeof this[method] == 'function' && this.hasOwnProperty(method)) {
  15. memberArray.push(method);
  16. };
  17. };
  18. return memberArray;
  19. };

In the getOwnMethods function we use the hasOwnProperty function to discriminate between methods declared in the object and methods inherited through the prototype.

13May/082

Dealing with comma delimited data in a database column

For various reasons, developers through the years have decided to store lists of data as comma-separated lists. Most programming languages include a split() function that allows you to break apart a list of data using a specified character. T-SQL does not.

I don't remember where I got this split function from. I know I didn't write all of it from scratch. But basically what it will do is take a delimited list of data, split it apart, and return a table where each data element is associated with the identity value you pass into the function. This is very useful if you just want to get the values for a single row.

CODE:
  1. CREATE  function Split
  2. (
  3.     @list varchar(8000),
  4.     @identityVal int,
  5.     @SplitChar char(1)
  6. )
  7. RETURNS @RetVal table
  8. (
  9.     id int,
  10.     Value nvarchar(1000)
  11. )
  12. AS
  13. BEGIN
  14.     WHILE (Charindex(@SplitChar,@list)>0)   
  15.     BEGIN
  16.         Insert Into @RetVal (id,Value)
  17.         Select @identityVal,value = (ltrim(rtrim(Substring(@list,1,charindex(@SplitChar,@list)-1))))
  18.         SET @list = Substring(@List,Charindex(@SplitChar,@list)+len(@SplitChar),len(@list))
  19.     END
  20.     INSERT INTO @RetVal (id,Value)
  21.     SELECT @identityVal, ltrim(rtrim(@list))
  22.     RETURN
  23. END

So what happens if you are trying to build a view or a report and need to split apart multiple rows. You can iterate over the rows in the table you want to flatten out and call the split function for each row, passing the rows PK into the split function.

CODE:
  1. create function fnFlattenMyTable
  2. ()
  3. RETURNS @RetVal table
  4. (
  5.     PrimaryKeyId int,
  6.     MyListValue varchar(100)
  7. )
  8. AS
  9. BEGIN
  10. Declare @PrimaryKeyId int
  11. Declare @MyListColumn varchar(6000)
  12.  
  13.  
  14. SET @PrimaryKeyId = (select MIN(PrimaryKeyId ) FROM MyTable)
  15. WHILE @PrimaryKeyId  is not null --main loop through MyTable
  16. BEGIN
  17.     Set @MyListColumn = (select MyListColumn from MyTable where PrimaryKeyId  = @PrimaryKeyId )
  18.     insert into @RetVal(PrimaryKeyId , MyListValue )
  19.     select id, value from [Split](@MyListColumn , @PrimaryKeyId , ',')
  20.     SET @PrimaryKeyId  = (select MIN(PrimaryKeyId ) FROM MyTable where PrimaryKeyId > @PrimaryKeyId )
  21. END
  22.  
  23. RETURN
  24. END

This function uses one of my favorite sql tricks. It uses a while loop to avoid having to declare a cursor . The logic is pretty simple, on each loop, select the lowest value of the PK in the table that is higher than the previous PK. That's the roundabout way of saying, "Select the next highest PK from the table".

Right now, this function is hard coded to flatten the table "MyTable", but it could be re-factored into a general use function.

Tagged as: , 2 Comments
3Mar/080

Modern JavaScript Development: null and undefined

In my last post on constructors and objects in JavaScript, I mentioned that the logical OR operator || was short-circuited and allowed us to set default values for arguments passed into the constructor. So we know that the argument evaluates to false if we don't pass it in to the constructor, but what value does the argument have that makes it evaluate to false?

There are three different values, or types, that a variable can have in JavaScript, null, undefined, and the value you set.

CODE:
  1. var isNull = null; //null type
  2. var isUndefined; //undefined
  3. var isNumber = 1; //neither null nor undefined, contains a value

A variable is null if you explicitly set it to the null value or if it receives a value from an expression that results in null; A variable is undefined if you declare it and haven't assigned a value to it yet. The tricky part about null and undefined is that they are equal, but are two separate types. Consider the following code.

CODE:
  1. var isNull = null;
  2. var isUndefined;
  3. alert(isNull == isUndefined);

So how do we differentiate between null and undefined variables? By using either the typeof function or the identity(===) operator. The identity operator has an evil twin (!==) that returns true if the object is not of the type you passed. The typeof function is defined in the JavaScript global object and returns a string containing the name of the type of object passed to it. The identity operator is a binary operator that compares the types of the two objects being compared and returns a boolean.

CODE:
  1. var isNull = null;
  2. var isUndefined;
  3. alert(isNull == isUndefined);
  4. alert(isNull === isUndefined);

n.b. If you pass "null" as an argument to a function, typeof will return "Object", but the object will === null.

CODE:
  1. function defaultArgs(name, options) {
  2.         alert(typeof(name));
  3.                 alert(name === null);
  4.                 alert(name === undefined);
  5.         this.name = name || "unknown";
  6.         this.options = options || { size: 42 };
  7.         };
  8.         var instanceOne = new defaultArgs("Scott");
  9.         var instanceTwo = new defaultArgs();
  10.             var instanceThree = new defaultArgs(null, {size : 43 });

So, how does this affect the logical OR operator? Well, both null and undefined are evaluated to "false" by the || operator, but the argument is still declared in the scope of the function and you can assign a default value to it. It's important to know the distinction between null and undefined. A function call may result in a null return value, a failed function call may result in an undefined value.