Because the .NET framework controls didn't plan in advance to be able to incorporate ASP.NET AJAX features into the framework, there can be certain things that make working with .NET controls harder. Take, for instance, the checkbox control. While this control is simple, to show or hide the checkbox is not as easy as simply accessing the element by it's ID and setting the style.display property to none.
A checkbox renders, with text, as:
<input type="checkbox" ../>
<label for="checkID">text</label>
So if you try to do this to hide the checkbox:
var check = $get("<%= checkID.ClientID %>");
check.style.display = "none";
The label element will still be visible. Using a separate <asp:Label> element and using $get() to return the reference to the label works as a way to get the checkbox label and show/hide it as well. Alternatively, the checkbox is wrapped with a <span> tag as such:
<span>
<input ..>
<label ..>
</span>
So if you want to show/hide a checkbox and the associated text, you can also do:
var check = $get("<%= checkID.ClientID %>");
check.parentNode.style.display = "none";
The parentNode method returns the reference to the parent node (the parent span tag, as the check object is referencing the <input> element). And thus, both the label/input tag are shown/hidden.
I had an import process that imported Excel data. But I didn't want to hard-code the name of the table being imported. To handle this, I found this article online by David Hayden with a solution: using the GetSchema method to get the schema of the underlying connected database. Check it out at: http://davidhayden.com/blog/dave/archive/2006/05/31/2975.aspx
I've been asked: "why use dynamic"? I admit, there aren't a lot of areas where dynamic is really needed. But there are some, and while I'd recommend limiting use of the dynamic keyword, I would never suggest not to ban it. One of the uses where I found it handy is with wrapper classes. I was developing a wrapper that looked like:
public class DataBoundWrapper
{
private Control _control = null;
public static DataBoundWrapper Create(GridView control)
{
return new DataBoundWrapper(control);
}
public static DataBoundWrapper Create(DetailsView control)
{
return new DataBoundWrapper(control);
}
}
I left out the constructor, but basically it takes the control reference and assigns it to _control. Now, to wrap I would do something like this:
public string DataSourceID
{
get
{
if (_control is GridView)
return ((GridView)_control).DataSourceID;
else if (_control is DetailsView)
return ((DetailsView)_control).DataSourceID;
}
}
This is because the GridView and DetailsView do not define some of these properties in a base class; they each define the same properties repeatedly. I personally think this is a limitation of the controls, but the design is what it is. THe DataSourceID property may not be the best example, but other properties like AutoGenerateColumns (or Fields), paging properties, and many more properties are not defined in a common base class or interface.
So a way around this may be to change the definion to use:
dynamic _control;
And have each property use now instead:
public string DataSourceID
{
get { return _control.DataSourceID; }
set { _control.DataSourceID = value; }
}
Now the control's properties are linked dynamically at runtime, and because both controls have a DataSourceID, this works and is a lot easier to implement.
When planning an ASP.NET AJAX solution, I'd recommend thinking about the total number of downloadable files that you site or class library will have. This matters because it can affect performance. Omal Al Zabir had a good overview of the problem and solution here. One of the solutions he provides is the ability to combine scripts through a component. The ASP.NET AJAX framework also added the ability to perform script combining as well, using the CombineScripts attribute of the ScriptManager, instead of the Scripts tag.
Outside of script combining, it's possible to have debug and release versions of your script. The script manager component has a ScriptMode property that can be set to Debug or Release. The ScriptManager knows whether the application is compiled in debug or release mode, allowing you to provide a collection of files in debug mode, while providing one single large file in release mode.
<asp:ScriptManager>
<Scripts>
<asp:ScriptReference Path="~/temp1.debug.js" ScriptMode="Debug" />
<asp:ScriptReference Path="~/temp2.debug.js" ScriptMode="Debug" />
<asp:ScriptReference Path="~/temp.js" ScriptMode="Release" />
</Scripts>
</asp:ScriptManager>
Here we have two debug scripts and one release script, as one script file has better performance. The challenge can come when you manage two sets of scripts though.
Another aspect to keep in mind is putting the security features all in one file. For instance, suppose for a blog section of the app, you have client-side AJAX features implemented, giving a few users the ability to perform some additional work. For all other users, they won't have these abilities. If you put the security features in a file: blogsecure.js, then what you can do is programmably control whether this script is provided to the user based on their role, using something like:
ScriptManager manager = ScriptManager.GetCurrent(this.Page);
if (this.User.IsInRole("BlogAdmins"))
manager.Scripts.Add(new ScriptReference("~/blogsecure.js"));
That way, the script doesn't even run, and this can help prevent potential hacking while giving the user full fledged functionality of inserting, updating, and deleting data asynchronously via web service calls.
Microsoft had some interesting presentations at the PDC in Los Angeles. Some of the newest features are (found from this http://channel9.msdn.com/pdc2008/TL16/)
- The new dynamic keyword, which allows for dynamic invocation of methods that you don't know at compile time. This dynamic keyword isn't like var although it appears to be. While var can represent any type, dynamic represents an object that will have its members dynamically invoked at run time. This allows for greater flexibility because normally you'd have to write additional reflection code, and this shortcuts this. There are some great examples.
- Optional properties in C#, which I should say finally this comes over from VB.NET. No longer do you have to specify every parameter in a method: you can use the following parameter syntax string name = "Brian" to assign a default value to a parameter in the method. This means you can leave out values, or specify optional values explicitly with paramName:"value".
- Eventually creating the C# compiler in managed code, making tapping into the compiler easier.
Some interesting stuff coming out of Microsoft. Stay tuned.
I recently got this error when applying a data fix. The error was for an insert that contains a select, I used the values keyword like:
insert into <table> (<fields>) values (1, 2, (select ...), 4)
The article referenced below indicates doing:
insert into <table> (<fields>) select 1, 2,(select ...), 4 -- notice no parens for outer select
You can see that post here:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=36506
In my talk, I was talking a little about the process of sending data from the server to client. In pretty much most data storage mechanisms or transports, the process of transporting data requires a serialization and deserialization process. For instance, if you push data to the database, you pull out the primitive data of some data object (whether be a DataRow, LINQ object, custom POCO object, or something else). You generally don't store the whole reference to the object and set the reference to the client. It has to be serialized.
What I actually found is that objects can be automatically serialized using the descriptor.AddProperty method. So when describing teh component, adding an object to the descriptor through AddProperty will automatically deserialize it correctly. Collections do not: this process is done via a JavaScriptConverter. An example of this is: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptconverter.aspx.
In this example, the converter serializes and deserializes the content using a dictionary of type Dictionary<string, object>. On the client, and object in the collection looks something like the following format: {"Text" : "2", "Value" : "2" }. A list as a string gets passed to the client that represents the whole collection. So in a nutshell, that is the serialization process. To deserialize it on the client, use the Sys.Serialization.JavaScriptSerializer.deserialize() method.
I wanted to say thanks to all who attended my presentation. I hope you found it worthwhile. I will publish the link where all of the code will be put at so the general public can access it. If you are interested in looking at an AJAX control/extender presentation and sample code, you'll find that shortly. I would assume the link would also be available here: http://www.cmap-online.org/
On October 25th, I will be speaking at the Central Maryland .NET user group at their code camp. The code camp is hosted at Loyola College Graduate Center and is open to the public. More information about this is at the following link: http://www.cmap-online.org/CodeCamp/. I will be speaking on developing ASP.NET AJAX control/extender development, of which I'm trying to write a book on the subject. So come hear me talk about this highly useful and interesting topic if you are in the area.
I found something interesting when dynamically creating a button in JavaScript. If I coded the button like the following:
var button = document.createElement("INPUT");
button.type = "button";
parent.appendChild(button);
button.value = "Click Me";
This worked fine, but if I reversed it to this:
var button = document.createElement("INPUT");
parent.appendChild(button);
button.type = "button";
button.value = "Click Me";
This did work, an HTML file error. Interesting.
I tried to define the following:
Public Class EvaluationCriteria
Public DisplayText As String
Public IsMet As Boolean = False
Hoping that I could get away with this. Turns out, as these two values are referenced in binding via the Eval() method, these don't work correctly. So it turns out, fields dont' necessarily work correctly with Eval. Didn't know that until I was trying to shortcut 
As I mentioned before, AJAX supports calling web services from the client using an XmlHttpRequest object. But sometimes, things don't go as expected. If you make the call, an error may occur in the web service, which you'd get an error prompt. However, there's one other aspect to this.
Sometimes the web service works fine, but you get an error with the breakpoint in the executor of the web service (ASP.NET AJAX code). There isn't a callstack, which is really hard to debug. What I've been finding out is that an error in the success or failed callbacks (which every web service supports a success or failed callback method that returns the results) will also act as if the executor failed, but that isn't the case.
If you use web services to stream data to the client via the ASP.NET AJAX framework, you may experience challenges when you use LINQ to SQL or Entities as your data model. This is because LINQ objects retain all of their relationships, which the serialization capabilities have trouble serializing entity sets and such. The workaround to this is to create an anonymous type.
The anonymous type entry works well, as long as the web service method returns an object. The anonymous type ensures that only serializable types are returned; any relationship properties can also be pushed down which makes it nice.
I got this error when trying to view the WSDL, and to access the web service via AJAX. The issue turned out to be easy; the type name in the ASMX file didn't match the full name of the class. I switched folders for this object, so I created it in a different folder, without changing the @WebService directive. So Visual Studio doesn't rename the paths whenever the folders change, and thus a manual change is required in the code-behind file and the @WebService directive.
I got the above error when passing data to a web service. On the web service, a field is defined as int?. But when I try to pass a null value, I get the above error because the value is showing up as NaN. So it sees NaN and throws this exception. As an alternative, I'm going to have to use a -1 instead, or convert the value to a string.
I chose the conversion to a string as the option to use as I convert the values to a string to pass in serialized form, which turned out to be the best option. It really worked well for passing data to/from client and server.
More Posts
Next page »