July 2009 - Posts

Recently, Rick Strahl blogged about his issues with MVC and using some of the essential methods were available in ASP.NET web forms development, considerably the GetWebResourceUrl method (as detailed here: http://west-wind.com/weblog/posts/842507.aspx).  The GetWebResourceUrl method is a useful method to reference files (CSS, JS, images, etc.) stored as embedded resources in an assembly.  In web forms originally, using the statement Page.ClientScript.GetWebResourceUrl would handle creating these URL's.

Rick notes that in your MVC views, you can continue to use some of these methods, but there are issues with using them because of the lack of the same page lifecycle you have in web forms, and how you can create a custom component to fill this void.  I would like to illustrate another possible option if you are looking to accomplish this within a controller.

But first, I have to take you back to ASP.NET web forms (my apologizes to those strongly in the MVC camp).  Web pages could have direct access to this ClientScript property (of type ClientScriptManager) to use GetWebResourceUrl, and so there weren't any accessibility issues within the page.  Within custom components, the HttpContext object gives you access to the page via the Handler property, which is the current handler processing the request (in case of ASPX files, this is the Page class).  In any component, it's possible to get a reference to the page (provided the page is executing the request) using:

Page page = (Page)HttpContext.Current.Handler;

Now that the page instance is available, an embedded resource can be retrieved using:

page.ClientScript.GetWebResourceUrl(page.GetType(), "<resource name>");

Again, this would be in some sort of component or outside the realm of the page; if in an ASP.NET page, user control, or custom control (or anything else that inherits from Control), you can reference the page directly via the page property.

Within MVC, there are several options.  The ViewPage class inherits from page, but as previously mentioned, there may be issues with this here.  However, the controller can also reference the page.  While not directly being able to access the page through a Page property, it can using a similar approach as mentioned above.

The controller class has a HttpContext property, of type HttpContextBase.  This class has a CurrentHandler property, which is a reference to the Page.  Through this, you can cast it to Page and call the GetWebResourceUrl method as shown below:

var url = ((Page)HttpContext.CurrentHandler).ClientScript.GetWebResourceUrl(this.GetType(), "<resource name>");

To get the URL from the controller to the view, you have to return it via the action result or assign it to the ViewData collection, so there are a few options.  Note I'm still learning MVC, so there may be other areas to do this, and there may be other caveats.

Posted by bmains | with no comments
Filed under:

There has quite been the ASP.NET vs. MVC debates going on the internet these days.  I must admit, I'm amused by it because it really comes down to personal preference, and what you are comfortable with.  Most importantly, it should be dependent on what's best for the project at the moment.  However, I do have one fear of what may be coming...

A while back, an open source initiative, Web Client Software Factory (http://www.codeplex.com/websf) was deployed as a viable option for creating applications using a composite development approach.  This was something similar to the MVC framework: a better object-oriented approach to what web forms gave you.  But since MVC came out, WCSF was last deployed Feb 28th, 2008.  And so MVC is the new platform to develop applications in this manner, and I'm thanking God I didn't attempt to build an application using a framework no longer being updated.

A similar thing is happening with LINQ to SQL; it's going away (it's still around, but it's solely being maintained so what good is it if you don't get any enhancements).  LINQ to SQL was created to get people into LINQ, only to tell them that you waisted your time because ADO.NET Entity Framework (not available at the time, and not released until many months later) was the future.  if you invested in LINQ to SQL, it would still work, but you don't get the cool enhancements, updates, and new development, and there isn't a migration tool that I know of.

Is this ASP.NET's future?   A good product to get people into .NET, but is no longer an important piece in application development?  Time will tell.  I actually have been reading about the MVC framework and do look forward to using it.  Don't take this as a "I'm against MVC" posting; I am not.  I just hope that those who invested millions of dollars into ASP.NET web forms will suddenly be looking at using a maintained product with no future.  I certainly hope that isn't the case.

Posted by bmains | with no comments
Filed under:

You may have gotten this error when trying to update data, as I recently did.  After reading up on the subject, I found this which helped:   http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/2bb60aae-7510-4eae-846b-1dad25f2f181

By establishing a log for the data context, I figured out what the issue was.  LINQ to SQL attempts to get the current object by retrieving all of the information using the previous values that weren't changed.  So if you have a 15 column table, and two values changed, LINQ to SQL attempts to find the record using the 13 unchanged values, and performing the update on the other 2, as something like:

update [dbo].Table1 set Field1 = @p13, Field2 = @p14 where Field3 = @p0 and Field4 = @p1 and ... [and so on]

So if something changed about one of those thirteen values, it won't find the record and an error will occur.  This is what I was doing; I posted recently about an issue with an exception being thrown when the foreign key already has the value.  If you have a PK reference as an EntityRef<>, if that reference is loaded, you cannot change it.  You can if you add a method to it that does:

public void ClearReference()
{
     _SomeType = default(EntityRef<SomeType>);
}

This actually clears the reference.  You can't do obj.SomeType = null because it detects the value has changed (even though its being set to null) and the exception still ensued.  So I originally was clearing both the key and the type, setting both to null.  Setting the key causes Row not found error because the original key no longer exists and it looks for a null check.  And thus, one of the 13 original values was changed without LINQ to SQL knowing it, and an error ensued.

Because I actually have to clear the variable, and not the property reference, I don't know if an extension method can be used to clear it; it is something I'm going to investigate.

Posted by bmains | with no comments
Filed under:

I got this error when setting up some LINQ to XML code and I couldn't figure out why I kept getting this error as it made no sense.  After doing a quick search, I realized my root element was this:

var o = new XElement("statement", query.Statement);

and I realized that it was housing content and couldn't be stored in this way.... the root element was a text node like:

<statement>some statement</statement>

And so, switching it to:

XElement queryElement = new XElement("query", new XElement("statement", query.Statement));

 

And so switching it to this, with a root element like:

<query>
    <statement>my statement</statement>
</query>

Helped.  The other thing that solved the issue was how I was creating the document.  I was trying to create the entire XML tree and then assign it to the document via its content property in the constructor.  This didn't work, and the solution was to first create the document, then create the root node and add it, along with the rest of the document.

XDocument document = new XDocument();

XElement queryElement = new XElement("query");

document.Add(queryElement);


Maybe that is a bug, I'm not sure, but I can't assign query directly via the constructor.  I get an error.

You can create the XML in one shot, via the way LINQ to XML works, but I can't in this scenario based on how I have to write the content out, which is why you don't see that in my example.

Posted by bmains | with no comments
Filed under: ,

Do we really even need IStateManager anymore now that we have ASP.NET AJAX?  In the olden days IStateManager was used to retain the state changes made to a list-bases resource.  These changes would occur on the server and be available on the next postback.  Let's provide a brief example, and I have the perfect one: the DropDownList control.  The DropDownList control (and other ListControl derivatives) have an Items property of type ListItemCollection.  This list class implements IStateManager, so any changes to the Items collection on the server is retained and "permanently" available, at least available while that page was existant.  So a page could bind a list, then later on use server code to change the list (say in a postback scenario), and these changes are retained.  Some developers even wrap the DropDownList in an updatepanel in order for this to work, or use the AjaxControlToolkit (ACT) extender to manage multiple related drop downs.

Note: I Expect You to Understand IStateManager and what it's used for beyond this point.

Now that the focus and the toolset is moving toward a rich client-side AJAX-centric applications, more based on JavaScript than using the server-based UpdatePanel approach, do we even need to consider IStateManager for any custom controls we may develop?  In some cases, I say no, that this isn't as much of a concern anymore.

In some cases, I still say yes, and here is why.  Suppose you have a list of drop down items for a customized drop down control.  Your control can and does manipulate the list of items on the client, while retaining an equivalent list on the server (which is the norm for ASP.NET AJAX controls in most cases).  You may want those two lists to retain the same values, and so one way to do this is to ensure the list retains its values using IStateManager, and post back the changes to the list in a hidden field or something else.

ASP.NET AJAX doesn't have a direct way to postback values, so storing information in hidden fields or another client-side mechanism is the common choice for doing this.  This means that a list of entries may be written in a JSON, or other, format and be processed on the server.  The server can process hidden field information in LostPostData, and thus modify the list at the appropriate time, which IStateManager can then do its work at the appropriate time.

My random thought for today (or actually tonight technically).

Posted by bmains | with no comments
Filed under: ,

You may have already noticed that it's harder to debug errors that occur within a Lambda expression.  For instance, if you have this Lambda expression:

var entries = collection.Where(i => i.EndDate.Value >= new DateTime(2008, 2, 1));

Notice the type that EndDate represents, naturally it's a date but it's also a nullable one, so it's Nullable<DateTime> or datetime?.  When Value is called, a value has to exist for EndDate; otherwise, an exception gets thrown because you can't call Value when the value is null (HasValue can be used to check for null).  But the issue with Lambda's is that they don't throw an exception immediately.

Rather they throw an exception whenever you do anything with the entries variable.  As soon as you may do "var entryCount = entries.Count();" an exception will be thrown, seemingly an issue with this line but ultimately pointing to the lambda.  Now, to debug, if its your method being called, the debugger steps into it.  Otherwise, for framework code, it doesn't (except possibly if you enabled CLR debugging which I didn't).

Posted by bmains | with no comments
Filed under: ,

You probably know that C# supports inheritance.  With inheritance, C# supports constructor inheritance of sorts.  This means that you can call a base class’s constructors in the derived class.  If you had the following class:

public class DerivedObject : BaseObject
{
     public DerivedObject() { }
}

This, by nature, doesn’t support calling the base class’s constructor.  Instead, you would do:

Public class DerivedObject : BaseObject
{
    public DerivedObject(): base() { }
}

The base() statement calls the base class constructor.  If the constructor has any parameters, these can be passed along too.  You may not want to call the base class.  There isn’t any point in calling the base constructor, unless the base constructor does something (like pass data to local variables or execute some sort of logic, which the latter isn’t recommended).

ASP.NET AJAX has this too; to define a constructor for a class that inherits from another class, you do:

DerivedJSObject = function() { }

DerivedJSObject.registerClass(“DerivedJSObject”, BaseJSObject);

Now, this scenario involves not calling the base class constructor.  Remember I said in C# it’s OK to not call the base class constructor.  In ASP.NET AJAX, it IS NOT OK to omit this call.  This is because ASP.NET AJAX does some important stuff in the base class call, through a special method.  This method is initializeBase, as in:

DerivedJSObject = function() {
    DerivedJSObject.initializeBase(this);
}

DerivedJSObject.registerClass(“DerivedJSObject”, BaseJSObject);

The initializeBase method takes the instance of the class, followed by any other parameters to pass to the constructor (in an array form of []).  This method is important because JavaScript doesn’t support inheritance.  Because it doesn’t, there are a coupleof ways to setup inheritance in JavaScript.  These options are:

I'm not going to go too in-depth into this because these references do a great job of explaining the concepts.

Posted by bmains | with no comments
Filed under: ,

I found out yesterday that I was renewed as a Microsoft MVP for another year!  I look forward to tweeting, blogging, and writing about Microsoft .NET technologies.  You can connect to me with the following:

Twitter: @brianmains
Linked In: http://www.linkedin.com/in/brianmains 

Posted by bmains | with no comments

I created a TWTPOLL for this very question.  Please submit your opinion:  http://twtpoll.com/2oqm0o.  Thanks for your participation in advance.

Posted by bmains | with no comments
Filed under: