June 2006 - Posts
I've been reading a lot about custom application design lately, and I have a book proposing using a dictionary or collection for storing properties in business objects. I wondered about that for a while, and while reading about object design, came across this article: http://www.codeproject.com/gen/design/AOM_Property.asp.
I guess I'm somewhat torn; on one case I see the lack of type specificity, as well as the potential to not know all of the values assigned (more so in a dictionary setting). However, I see the power in this, as after reading it, I saw some of my own limitations and excessiveness in my code. It makes sense to use an attribute collection for properties.
But I also have to wonder whether that will make it worse with all of the boxing and unboxing of values that will occur. Maybe not so much from a performance perspective, but a design one. I think that is one of the reasons developers do prefer creating properties in the objects directly.
I have to say that is a better approach in some situations (although I wouldn't implement it in a factory pattern), but there is something in me that makes it feel different or awkward for me, as if it is an unnatural way to do things, even though it may be better........
Both C# and VB.NET support XML comment notation (/// or ''') in 2005 and, when a project is compiled in Visual Studio 2005, a file is created that contains a complete listing of all comments made for classes, methods, properties, etc. This is a great feature because it immediately makes available all of the documentation into one file.
One of the things I played around with was the ability to add additional XML tags. For example, in my Data Access Layer, I added a <storedProcedure> element, which compiled to the XML documentation file as well. This way, I also knew which stored procedures I was actually using in my data components. That is a great feature.
Precompiling is a new option of the .NET 2.0 framework. Sites can be precompiled so that whenever a user first enters the web page, the site is already compiled with the changes. Previously, whenever a 1.1 framework page was first accessed, there was a performance decrease because the page had to be compiled on the initial load. With precompiling, this performance decrease isn't an issue.
However, you have to keep in mind that you can't change the content for ASPX pages dynamically; instead, you have to recompile everytime you make changes to a compiled file. This is because precompiled ASPX files no longer store the HTML in the file; rather the file is a "stub" or "marker", noting that the file exists, but the code is retrieved from a DLL. If you look in a precompiled site's bin folder, you will notice a lot more compiled files and dlls than you do under normal build circumstances. That is because this usually occurs on the fly.
I created a batch file to do the creation for me, because it involves using the framework's aspnet_compiler executable to do the creation. This utility uses either the physical (-p) or virtual (-v) path (as well as other options), and the folder to output to as the second parameter. I also included a remove directory command because precomiling requires a new folder, and as such, my script looks like this:
rd /s /q c:\precompiled_site
<path to 2.0 framework>\aspnet_compiler -v virtualFolder c:\precompiled_site
pause
See this for more details: http://msdn2.microsoft.com/en-us/library/ms229863.aspx
I would like to talk theory for a little bit about friend methods. There has been some talk over whether you should or should not use friend methods. If you take a look into the .NET framework API's you are bound to find heavy use of friend methods, properties, and classes. However, some people have said never to use them.
I see wisdom in both lines of arguments. Friend functions can be a problem because if you rely on them heavily, it opens the constructors, methods, and properties up to many possible internal access points, which could result in overwriting previous values. In my own coding experiences, I've seen several times where the use of several friend functions made the code more bogged down through the approach I used, instead of using an alternative approach with public properties/methods instead. A method in one class called a method in another, and it created sort of a networking scheme of friend function calls, which can become unmanagable. Instead, a refactored approach made it more manageable.
However, there were times, when being consistent with friend functions, increased the efficiency of the API. In one example, because of loading data in a consistent way, using a friend function in the class that was having the data loaded made it more manageable when editing code dealing with that class; all data access code was centrally stored in this one object. Then, the parent object that needs to populate it can call this loading method to load the data. Any object needing to load the data can also do so, using one method call.
I think friend functions need to be limited in their use, but not eliminated. When using them, extra care is needed to ensure that it isn't making the code unmanageable and adding extra complexity. Keep in mind all of the access points that friend functions open your code up to, and try to keep it to a minimal set. Sometimes, realizing an alternative approach can lead to a better design.
The new Security Application Block in the Enterprise Library Jan
edition authenticates and authorizes users in windows and web
applications.
In an article I wrote, I tackle authorizing users using the Roles provider to create an IPrincipal object and authorize the user for a specific task.
The
security block uses rules-based processing for validating users for
specific tasks. A rule specifies which user or role has permissions to
it. When you authorize a user, you specify the rule name determining if
they have access, and the method returns a boolean value stating that.
It
is important to understand the concept of declaring more rules than are
necessarily needed. Breaking out rules instead of using one rule for
many tasks can make maintenance on an application harder later in the
development cycle, especially if you need to add a role for an action
for only part of the rule. For instance, if you use one rule for
insert, update, and delete actions, but later you want to add a role
for insert and update actions, then you need to change your code.
Otherwise, if the rules were broken out for each action, this
modification is simple.
I develop with Visual Basic 2005 at work and there was a reported problem with
the compiler that would throw errors whenever doing simple tasks in
Visual Studio .NET. It was a problem because it would frequently
happen, and after selecting the do not send error report to Microsoft
option, I would lose intellisense support, and much more that makes
Visual Studio .NET a great product.
If you have these problems,
there is a hotfix available; SP 1 is slated towards the later half of
the year, so it would be useful to install the hotfix now. You can find
it at:
http://support.microsoft.com/kb/915038
I recently ran across a problem with FindControl in a content page in
ASP.NET 2.0. The content page was using findcontrol to dynamically get
the reference to a control, but the problem is using the ID no longer
works as in ASP.NET 1.1. You have to use the unique ID to get the
control, which if you know about the process, is the master page
control ID, then parent controls, then your control you want to get.
So, if you want to get the control using the control ID, you will have
to create a custom FindControl method that iterates through the control
collection. Not fun.
For example, here is the ID of a control in a user control, which isn't really easy to get at the name:
ctl00_cphBody_wucEventCalendar_calEvents
I have a page where I cache the data, but set the gridview's
enableviewstate to false, which means that I load the data on every
page load. This makes a section, where I load a lot of data, go faster,
because the gridview doesn't have to hold the large viewstate, and the
roundtrip is quicker that way. But, I have the data in the page, then I
trigger a search. The postback occurs, and the gridview is bound to the
old search results, then the button click fires, the new search results
are retrieved, then the grid is bound again. I wanted a way to avoid
that.
I found that the Request.Form("__eventtarget") has the ID
of the control that is responsible for the search. So by checking to
see if the ID of the linkbutton fired is in the __eventtarget field, I
can avoid initially loading the data in the page load, and only load
whenever the linkbutton is clicked.
This even works for
linkbuttons in a user control, because the ID looks something like
ctl100$wucUserControl$lnkSearch, and if you do a search for:
if (Request.Form["__eventtarget"].Contains(this.lnkSearch.ID))
//skip loading
I
get errors when nothing is there, so I usually wrap it around a try
catch block to avoid that. If it is found, then I exit the page load
event; otherwise, continue processing as normal.
I was using a strongly-typed dataset in one of my projects when I noticed an error I was getting:
"Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints."
I
was checking around and found out that the fields in the DataTable have
a NullValue property, which specifies an action; it can be empty, null,
or throw an exception. Each one was throw an exception, so I changed
that quickly for the null fields. But that didn't solve the problem. I
was looking around on the web, when something got me thinking; I
double-checked my select query, and it turns out I wasn't returning all
the fields as shown in the data table; once I added the missing field
to the query, everything was back to normal.
I actually like the Enterprise Library, manually coding the access to the database, to retrieve the data from the database. I don't like how the datasets are generated, as it may not always easily work in customized situations, and I wanted to be consistent with my data access. Still, for RAD development, it is a good tool to get things started, if at least temporarily until another release.
The two controls listed above provide mechanisms to upload files to the
web server. With the 2.0 framework, the FileUpload is a server control
equivalent to the HtmlInputFile, and provides some additional
enhancements to the control. It adds a HasFile property stating if a
file has been selected in the upload box, as well as additional file
accessing properties directly in the control, instead of referencing
PostedFile. I did notice one quirk; the FileName property in FileUpload
only contains the name of the file; the FileName property in the
PostedFile property contains the entire path.
One other point;
these controls do not save their viewstate. LoadPostData always returns
false, and the Value property is readonly. You can inherit from the
class and override LoadPostData to return true and try to restore the
value, but value is readonly. I did read about that it may be possible
to set the value through javascript, but in all my attempts, I failed,
so I gave up on it.
If you want to create one to restore viewstate, you have to look at that as an option.
Here is a
multiple file upload control
that I created, which renders multiple upload boxes so a user can
upload in bulk. The only problem is this control does not retain its
state across postbacks, and as such, you have to create the number of
boxes you want first before you browse to the files.
I was binding to the Membership class, but it didn't come up in the
dropdown in the configuration tool for the ObjectDataSource in the designer. So as an
alternative, you can type in the TypeName property, set to the
System.Web.Security.Membership type. After that, go back into the configuration tool. You'll be able to get all of the methods in the drop down for
the Select, Update, Insert, or Delete methods, so you can use the designer this way instead of doing it manually.
Here's
an article
I wrote on Custom EditorPart controls. These editor parts are cool,
because they render like any other control, and work dynamically to
edit the values of a class that inherits from the WebPart class.
Classes that implement IWebPart can't use this functionality.
In my custom pages, I was overriding the ID property of the Page. I
wanted to use this to return the name of the page ("default.aspx") to
whoever is using it, to make it easier to reference this. But because
of this, I got an error "key cannot be null: parameter name value".
When I removed this, it fixed this error. So, in case anybody had a
similar problem.
I was getting selected data from a data component, but I was running
into a problem where when the ID was not present (invalid value), and an error
is thrown. This is of course correct; however, the ObjectDataSource was
calling the method to select the data, even when no valid ID value was provided (this was a
master/detail type architecture, where the gridview selects a row, then
this ODS is fired with the appropriate ID value; however, on the
initial load, no ID value is selected). So I was looking at a way to
prevent this, and came across the Selecting event, which fires when
trying to select data. I did a quick comparison against the ID, and if
not a positive value, cancel the selection. Here's the code:
void ods_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
if (int.Parse(e.InputParameters["intID"].ToString()) <= 0) e.Cancel = true;
}
I was having a problem binding to a business component that I had. I
was binding to a business component that returned a datatable with the
results to a GridView, but I was getting errors that a property (the
connection string key, which I pass dynamically) wasn't being provided,
and the data component I use was throwing an error because of it.
That
was the correct behavior, because I didn't want the data component
having no key to work with. So instead, I was looking around, and found
the ObjectCreated event. This event contains an
ObjectDataSourceEventArgs event argument that has the instantiated
object (through the ObjectInstance property). I could then convert the
type to the appropriate type and pass the value, before the binding
took place. An example would look something like this:
private void ods_ObjectCreated(object sender, ObjectDataSourceEventArgs e)
{
if (e.ObjectInstance is MyType)
{
((MyType)e.ObjectInstance).Key = "my key";
}
}
More Posts
Next page »