Monday, June 30, 2008

My blackberry just threw an exception. The consumer in me thinks oh, $%^@#$. The programmer in me thinks that's so cool, I wonder what did it. A hard boot got the thing going again.

Monday, June 30, 2008 8:41:13 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, June 24, 2008

The basics for the login pages are done. A few more tweaks and that will be done.

It might seem like I take forever but in truth, I don't have many hours a week to give to this pet project right now. I hope to have more time this fall.

 

Tuesday, June 24, 2008 7:39:38 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Wednesday, June 04, 2008

Now that I'm diggging a little deeper into my pet project web site, I'm learning how I really use the data. The Get() methods provided by .netTiers are great but I thought I would have more. I started looking at my database starting with the aspnet_Membership tables. I would expect unique indexes on something as obvious as the email column but it is not there. Same goes for other obvious columns in these microsoft-provided tables. So I add unique indexes to the membership tables. Of course, I do the same for my own custom tables and find that some of the text or varchar(max) have to be changed. No biggie but another step I have to take.

Now that the database is set, I need to regen the .netTiers templates, rerun the GrantUser stored proc, build the .netTiers stuff and copy it into the /bin of my project. Not hard work but just tedious to get each step completed and move on to the next one. All this so my .Get methods are consistent with my usage of the library.

All this so I can get my validators working - I really hate validators.

Wednesday, June 04, 2008 8:35:07 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Tuesday, June 03, 2008

Yesterday, I was reading the MSDN FLASH email newsletter and saw a listing for another SQL injection article. Since one of Wayne's sites was recently hacked, I thought I would read it. The article is clear and gives explicit steps to take. Since I had only done one of the three things (SQL stored procs), I thought I would mess with the last one: execute permissions only.

Wayne pointed me to a stored proc to grant permissions to a user. Since users and roles are one of those areas that after you have them set up correctly, you don't mess with them, I stumbled my way through creating a user. I ran the stored proc (which will have to be run after every .netTiers generation), modified my sql connection in web.config and tried my pet project site. I get an error about SELECT statements and permissions. .netTiers was supposed to be configured in web.config to use stored procs but apparently not. So I change the file, build, and still get the error. Someone, somewhere is caching something. Close everything done. Reopen. Change web.config and checkin with comment. Test again and it works.

This is a really bad way to find a problem. It's getting to the point that I need someone to check my security changes so this type of thing isn't missed.

Tuesday, June 03, 2008 7:00:10 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, June 01, 2008

Volume 14 of Make Magazine has an interesting article on free web sites - web site builders that also host the end resulting web site.

Sunday, June 01, 2008 6:52:45 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, May 29, 2008

Here is my latest article on 15seconds.com: http://www.15seconds.com/issue/080529.htm titled "Implementing the .netTiers Template Library as a .NET Website's Data Layer - Part I"
 

Thursday, May 29, 2008 6:22:45 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, May 28, 2008

Now I'm trying to get all my blogs tied together. Most are DasBlog so no big deal only what is the endpoint? The documentation lists blogger.aspx off the root but the file isn't there. Apparently from the forums I'm not the only one with the issue. However, I thought I bet it is there virtual. So I enter that in the address bar and I get a response of web service methods available. Nice - why doesn't the documentation say the page isn't there but the dll will respond.

Wednesday, May 28, 2008 8:46:55 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, May 08, 2008

I get an email every friday about the new events for families on the weekend on www.neighborhood-kids.com. The design is great. I love it, but my eyes and mind do skip over things in the page just assuming they are pretty but useless. Then I noticed the clock at the top of the page was right about the time. Wow, that is cool. I'm going to have to pay closer attention to what is technically happening on web sites.

Thursday, May 08, 2008 8:14:25 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, May 02, 2008

Living in the northwest is wonderful but when spring and summer start to show up (meaning the sun makes a regular appearance), I totally loose all motivation. My brother from England worked a summer for Boeing in Seattle a few years ago. He was shocked that people didn't do any work in the summer. I was always luck at Microsoft to not have a summer ship date. That would have totally sucked.

How can I think about writing code and the project when the sun is out just laughing at me, taunting me to come out.

Friday, May 02, 2008 8:08:07 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, May 01, 2008

There are a few times in my life when a project phase just goes on forever. Back in my Microsoft days, I hated the last stages of the ship cycle. People were burned out, higher-ups were already on to the next phase. Front-line devs, testers, pms, and writers were either too burned out to function or too hyped up to listen. The mid-level guys were running interference every which way. The bell-curve was watched and the marketing dicks were breathing down everyone's throat and lord help you if you broke the build. I was thrilled when my boss finally made the rounds to ask if I thought the product was ready to ship. He asked everyone personally instead of some meeting where the team bully could badger me into saying something I would regret.

And here I am with my own project in the end of one of the first phases and I trudge on. I'm not near enough done. No ship award in my near future.

Thursday, May 01, 2008 8:01:36 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, April 22, 2008

I'm moving some duplicate code from a codebehind file to a class file so I can reuse it. I'm tired and it's a bit late for my best programming so I'm trying to remember is the c# return type also null now. Or maybe no return type needs to be specified if a variable isn't returned (is that vb?). If null works in SQL and it works an an object value to compare against in c#, why can't null be a valid return type instead of void. What does void really say under the covers that is so different from null. Isn't void a carryover from c and c++. Perhaps it's older than that. Why do I need to remember yet another keyword that has no value. No, that's not a pun. I have too many numbers and words in my head that have to be pulled out at a moment's notice. Why add one more? Get rid of void. Just rip it right out.

C# | Dina
Tuesday, April 22, 2008 7:43:33 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, April 21, 2008

I'm still cleaning up code. One of the things that has never worked in NetTiers is the Microsoft Enterprise Library Exception Handling. I would get an exception thrown in the NetTiers code and the line was an exception with no data. I would get the error on a SQL insert via the NetTiers layers but no information about what was wrong with the data. Since I'm using the Insert where the param is the base type such as

   userService.Insert(newUser);

I knew that datatyping from a C#/.Net perspective wasn't the problem. I knew it was at a SQL level but I didn't know what it could be. So I finally had to fix the .NetTiers ExceptionHandling. I'm not sure why doesn't work right off the bat like the rest of NetTiers but I also didn't care enough to investigate. Once I get the ExceptionHandling working, I don't ever touch so I haven't had to REALLY understand it.

But now it has to work, it's hard to move forward without inserting data on this particular table. I knew I didn't have anything in web.config for this so that's where I started. I opened the ExceptionHandling Basic Quickstart and looked at the app.config. There were two different sections I added and then the true SQL error was displayed. While this isn't the entire work I'll have to do with Exception Handling on my pet project, at least I can keep going.

The SQL problem turned out to be that a datetime value was not being passed for a column where NULL was not allowed. Once the error handling showed the problem of datetime out of range, and I looked at the column definitions, I realized the problem.

Here are the sections I added to web.config:

1) in the <configSections>

<section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" />

2) the last entry before the end <Configuration> tag:

<exceptionHandling>

<exceptionPolicies>

<add name="Global Policy">

<exceptionTypes>

<add name="Exception" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="None">

<exceptionHandlers>

<!--<add name="Wrap Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" exceptionMessage="Global Message." wrapExceptionType="ExceptionHandlingQuickStart.BusinessLayer.BusinessLayerException, ExceptionHandlingQuickStart.BusinessLayer" />-->

<add name="Custom Handler" type="ExceptionHandlingQuickStart.AppMessageExceptionHandler, ExceptionHandlingBasicQuickStart"/>

</exceptionHandlers>

</add>

</exceptionTypes>

</add>

<add name="Handle and Resume Policy">

<exceptionTypes>

<add name="Exception" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="None">

<exceptionHandlers />

</add>

</exceptionTypes>

</add>

<add name="Propagate Policy">

<exceptionTypes>

<add name="Exception" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="NotifyRethrow">

<exceptionHandlers />

</add>

</exceptionTypes>

</add>

<add name="Replace Policy">

<exceptionTypes>

<add name="SecurityException" type="System.Security.SecurityException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException">

<exceptionHandlers>

<add name="Replace Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" exceptionMessage="Replaced Exception: User is not authorized to peform the requested action." replaceExceptionType="System.ApplicationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

</exceptionHandlers>

</add>

</exceptionTypes>

</add>

<add name="Wrap Policy">

<exceptionTypes>

<add name="DBConcurrencyException" type="System.Data.DBConcurrencyException, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException">

<exceptionHandlers>

<add name="Wrap Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" exceptionMessage="Wrapped Exception: A recoverable error occurred while attempting to access the database." wrapExceptionType="ExceptionHandlingQuickStart.BusinessLayer.BusinessLayerException, ExceptionHandlingQuickStart.BusinessLayer" />

</exceptionHandlers>

</add>

</exceptionTypes>

</add>

</exceptionPolicies>

</exceptionHandling>

 

 

Monday, April 21, 2008 7:10:16 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, April 20, 2008

Now that I have 90% of the v1 features for my pet project web site decided, and have a bullet-proof process for new tables, custom procs and other stuff NetTiers handles, I'm cleaning up the code. I'm ripping out any code I wrote to go against the SQL server that NetTiers handles for me. I'm cleaning up all gridview and codebehind to be consistent with naming and usage. I'm removing files that were tests to see how I wanted something to work. I'm removing links and cleaning up the masters.

Wayne suggested I change a feature from random choice to numeric order choice so that a progression was predectible. I've been fighting it but he finally gave me a business logic reason. Ok, so now I'm changing SQL table column data types. That dominos into all sorts of changes.

Once all this gets back to working, I'll start on the visual design. I haven't written themes and skins so I'm going to try to grab a working set that is close to my overall design. I'll implement it then dink with it till I get the look I can live with short term. Them I'll hand off the theme/skin to a graphic web designer. I don't mind paying for this because I definitely see the value.

Do you have a graphic designer you like?

Sunday, April 20, 2008 12:08:15 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Saturday, April 19, 2008

Wayne and I are remodeling our kitchen. In the process, we are shopping for cabinets. We want quality cabinets in the look that goes with our craftsman home. The high-end price is twice as much as the next quote down in dollar value. While we aren't comparing apples to apples, we are trying to. I keep comparing our kitchen remodel and new-construction backporch to a web site. I know nothing about cabinets and most web site clients know nothing about quality web sites. One of the cabinet salesman said the cabinets were guaranteed for life. No software manufacturer would ever say that. Some pointed questions reveled that only certain things were guaranteed.

What should a non-technical client expect from your final product? They won't ask all the questions you know they should. So lets work on some quality questions:

1) What error detection, communication, and recovery is provided? No one expects it to break so they won't ask this unless they have been burned by this.

2) What, if any, part of the code do they own and can literally walk away with? Are you letting them use your code base you already developed for a fee with a few new custumizations or is this new work written 100% by the web company? Same question for any graphics, images, code libraries, web services, etc?

3) What availability and time frame will you provide for fixes? Is this a scaled situation where only mission-critical bugs are given 24/7 coverage? Or are you tossing the web site over the fence and walking away?

4) What testing will be provided? Who does it and how do they determine the web site is of a certain quality bar? How is the quality managed internally? How is it communicated externally back to the client?

We all want to think we have a certain standard for code quality but how do we communcate that? How do we stand behind it? How do we demonstrate our code meets our own standards? You can song and dance your way around this so the client buys any thing you say but at the end of the day you still know if you meet your own standards. But how?

 

Dina | SYWYOW
Saturday, April 19, 2008 12:10:34 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, April 18, 2008

My pet project is a new website. I'm working on the search page which searches through several NetTiers Services in the Component layer. It took me a few hours to figure out exactly what I wanted to do here. Do I user an Object Data Source? User StringBuilder to return an HTML table? What should the gridview link to once the search has been performed?

Then I thought, I know I'm just going to AJAX this code. Am I just wasting my time? I just want to get v1 out the door. AJAX can wait to v2 but then I think none of this code would be used via AJAX except the NetTiers stuff.

Do you design new websites via AJAX right off the bat? I haven't done enough AJAX to be able to think AJAX as a first pass on the design.

Friday, April 18, 2008 7:12:00 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, April 17, 2008

If you have a full-time job programming, you might do something else in your spare time. However, I don't have that situation. I get my fill from 7pm to 10pm at night due to my current situation. I left a non-programming meeting last night and rushed home to start up VS and keep going on my project. I was thrilled to still have a couple of hours left before I had to stop. Then hubby starts watching HULU.com. Arghh! We sit next to each other in our office so this was not as conducive to programming as say...a jackhammer might be. Tonight I'm in the other room while he hulu's on.

Thursday, April 17, 2008 6:33:29 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, April 14, 2008

NetTiers will build methods for normal CRUD as well as anything they can determine. For example, if you have a table with 1PK and 2FKs, the template with build a method for select where the IN params are the two FKs. Great! I probably need that. But things get a little weird when I need to search. For example, I have a user's table and I want to be able to return results for all users that are like a searchterm. How about all user's like Dina. In T-SQL, I usually would have a where clause " UserName like '%@UserName%'. Works for me.

NetTiers has a Find method for each table. When creating a find proc, it's hard to determine which columns you would want to search through. NetTiers discovery does a bit of assuming that the first column (after the PK/FK columns) is THE main data column (such as a name). But that takes some forethought in terms of table creation. The NetTiers find method comes in two varieties: one with sql params in the NetTiers format and one with a SQL where clause. The NetTiers template should let you turn off this second way but it doesn't. Inside the stored procs that NetTiers creates, they put the where clause together. This makes me a bit nervous. I don't want a user entering something in a search textbox and have it passed to build a SQL query on the fly.

I'm going to write my own custom search proc sing the NetTiers naming conventions so I get a custom Find Method from NetTiers. I know what columns I want to search through on the Table but I also want to get my results in two line of c# code via NetTiers layer.

Monday, April 14, 2008 8:50:20 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, April 13, 2008

So now you have a business website and you control the content. It provides enough functionality that 70% of your needs are covered. However, you have a custom process that needs to be available on your website. This can be a common function that your Site Builder provider did not provide with your packaged website or it can be something specific to your business.  How do you make this available to your customer base from your website?

A few assumptions:

  1. You purchased your domain name, such as MyBooksForSale.com.
  2. You can describe in detail your custom process. Common web functionality such as a shopping cart does not need to be designed. Good examples of a custom processes are: pricing models, data exchange (possibly in files such as blueprints or accounting spreadsheets). 
  3. You have the time and money to maintain the available of this process to your customers on your website. Once the process is made available, you can fulfill the end result if there is one.

So what do you do now?

Local Rules. Bellingham is a small town (50K-70K population) and the techie group here is small. Word of bad work or work left undone gets around. Find a local web site that you like the looks and feel of, then approach the owner and quiz them.

Define a design budget for this process. Is it worth $10,000 or $100,000 to your business? Don't let a Web Design firm set the budget. If they want $100,000 for the process when you want to spend $10,000, one of several things could be happening:

  1. your expectations are not realistic
  2. their design is bloated
  3. your are not communicating clearly

Let's take Amazon as an example for a design: making book purchases available on the web. A small design would be to choose a book, and communicate the interest to purchase the book. The budget design allows for a list of books with the ability to select and send contact info. Your business could call the customer back for the actual purchase and fulfillment. That puts a lot of work on you as the business owner but it is within your budget. Then there is amazon who has every possible feature associated with book purchasing including one-click. Their site cost alot more than $100,00.

Define a maintenance budget for this process. Just like your existing web site, this new feature will have to live somewhere which will not be free. My current thought on joining an existing site from one of the Site Builder's to a new process is to use your domain name. For example, your existing web site was probably www.MyBooksForSale.com but your new process will live on a new location such as repairs.MyBooksForSale.com. There is some technical stuff to make this work but it does work. You can still have and manage your main web site inexpensively and then add a custom process. Any web design firm should be able to help you make this work.

Define a time frame for this process. The web design firm should be able to give you dates for you review of the work as it progresses. Each meeting should be an opportunity to refine the design and fix anything that isn't working for you. However, most design firms will have a standard process to stop "feature creep" which means you want more than you originally communicated and you think this new feature should be covered in the original bid for the work.

Courting and the Marriage. You will probably be working with your web design firm on a regular basis for a while, make sure you like them. That means they understand what you want and you understand what they can do. You communicate well together and progress toward your goals is made in a way that you enjoy. The flip side of the coin is that you pay your bill to them on time which means as soon as you get it.  

The WOW factor. Every web design firm will have features, techniques, technologies, or business partners that they think you can't live without. They love them and want you to love them too. They want to WOW you with them and then you'll want them too. You will feel over your head in an area you are unfamiliar with and you will want to say yes just to get to your goal. Keep focused on the goal of your business process on the web and make the WOW thing something that you'll consider after your initial process it up. Of course, they'll say it can't wait, it won't work without it. Get a second opinion from a professional. 

Test.Test.Test. Your process is ready to go and you just want it available to your customers. Stop and test your process. Ask you family, friends, employees to test it for you. Do not let your customers see this process unless you are sure it is ready. Don't expect the web design company to test it to your satisfaction because you know your business, they know how to build web sites. This is the last check for any communicate errors.

Evaluate the benefit of the process. After the process is live on your website and your customers are using it, find out a few things: 

  1. How do your customers like it?
  2. How would they improve it?
  3. How much more/different/better business is it bringing you or time/expense is it saving you?
  4. Would you have do it again? This process? This design firm? This way?

 

Dina | SYWYOW
Sunday, April 13, 2008 11:48:54 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Saturday, April 12, 2008

My site has two roles: Admin, SecureUser, and three types of content:Admin, SecureUser, Public. I found that the code in the last post from Jeff Prosise wasn't managing roles in the SiteMap. For a visitor to the site that has not logged on (anon), the site map improperly showed Admin and Public pages. I checked the web.config and the SQL statement so it had to be either the database caching or the sql provider for sitemaps.

I google'd and found several posts in 2006 about this but none since so I knew it had to have been resolved. I found this blog post by Ishai Hachlili that had the code to deal with roles correctly. I added the code and the problem went away.

I'm not sure the code is robust enough to handle a large site but it fixed the problem for now.

As an aside, several of the 2006 posts said to just fix the web.config by making sure the <location> tags were correct. This meant any user could see links for the site that were restricted but would be denied access once they actually clicked on the page.  The location tags are only one solution to the problem. You need to have the sitemap, roles and the <location> tag to solve the problem. I go one step further and have the master page (1 for each area of the site) check the user and deny access.

 

Saturday, April 12, 2008 1:04:33 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, April 07, 2008

I stared working on my sitemap tonight. Never done the SiteMap stuff before. Opened my Pro ASP.NET 2.0 in C# 2005 that I use as a jump off point for intro topics I haven't touched yet. The chapter is great but I like my data in the database which gets backed up every night. I understood enough and even got a test page up using nested site map files. Hurray!

Now on to the SQL provider. I knew there had to be one so I googled and found an article with code by Jeff Prosise. The article covers the .cs file that is the SQL provider, as well as the web.config changes, the T-SQL, and the aspnet_regsql commands.

After you get the provider up and working, don't expect the SQL provider to show up in the Data Source Configuration Wizard:

You'll have the change the SiteMapDataSource to specify the Provider that you added to the web.config for SQL:

<asp:SiteMapDataSource ID="TotalSiteMap" runat="server" SiteMapProvider="AspNetSqlSiteMapProvider" />

 

But now my data is in the database and I changed the proc to be NetTiers-compliant so I can use their Admin pages for my data management.

Monday, April 07, 2008 8:22:52 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, April 06, 2008

The Problem

I want to show a page with all the user-settable properties. Any properties that the user hasn't set should be shown but the value should be empty or null or some nice text indicating such. However, what is the BEST way to design this?

The Tables

I have a [Properties] table. I have a [UserProperties] table that has a FK back to [Properties]. There is only a row in the [UserProperties] table is the user has set one. If not set, no row. So back to what I want to show: in the user's account area, a page of all properties where any properties that have been set show that value, otherwise some text indicating the property has not been set. I'm going to go through every option to go from DB design to .Net code for the page that Wayne and I discussed on this fine rainy, sunny day.

All SQL

Most obvious from a database perspective: T-SQL join (1 db call) that includes all properties so depending on how it is written, right or left join. The problems with this are that the NetTiers layer is table-based. So I'm returning the properties for the user, but if the [UserProperties] table doesn't have the record, then NetTiers can't make an Entity object for that record because it requires the [UserProperties] PK for creation.

All .Net

Most obvious from a .aspx perspective: N+1 db calls. First page is a list of all properties (1 DB call), with each row using the userproperties entity for that property (1 call for each property). Any property that doesn't have a valid object in the userproperties shows text saying the property is not set. I hate this approach. This means both SQL and .Net have to chug through unnecessary work. Yuk. Yuk. Yuk. However, I can write it quickly. Hmm, write it quickly but spend eternity hating what I've done. Or scratch my head some more.

Other Answers

Less obvious: Work with NetTiers to have a custom proc and custom c# code to get this working. This should be easy. I know the proc code and I know where to tie into NetTiers. However, I still have an entity without a PK. Hmm, I'll have to think some more.

Less obvious: I'm using NetTiers as a stand-alone Library so how about sub/super class (depending on your perspective). Add a custom User class to my library that does what I need to do with a Properties object and a UserProperties object. I don't see how this reduces the db calls.

So far, I don't like any of these but I have a low-traffic site so I'm going to opt for the All .Net answer until I come up with a much better answer. Perhaps the table design is the problem.

Any thoughts? Suggestions?

Sunday, April 06, 2008 7:40:24 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, April 04, 2008

I love it when I'm just cleaning up some code after some major changes and I discover code that has been sitting there a while that would never have worked. I don't even have to run/test it. I can read it and know it's broken. So is that a win for finding a bug and fixing it before it showed up or is that WTF? for having such an obvious bug in the first place.

Friday, April 04, 2008 12:36:19 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, April 03, 2008

The days when I don't have to deal with web.config are great. The days I have to go in there are bad, bad, bad. Why can't web.config be easy? Why can't it tell me more, and complain less. Why can't it be easily organized in some sort of logical pattern instead of loosey goosey? The registry looks great compared to web.config.

Is this fixed in the latest VS or .Net?

 

Thursday, April 03, 2008 8:38:24 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Monday, March 31, 2008

And finally Wayne's Codesmith version for all procs prefaced with 'aspnet_':

<%@ CodeTemplate Language="C#" TargetLanguage="C#"  %>
<%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="System.Data" %>
<%@ Assembly Name="System.Design" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Import Namespace="System.Data" %>
USE [<%=SourceDatabase.Name%>]

GO

<%

foreach(CommandSchema command in SourceDatabase.Commands)
{
 %>
 
 <%
 if ((command.Name.Length>7) && (command.Name.Substring(0,7) == "aspnet_"))
 {
%>
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[<%=command.Name%>]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[<%=command.Name%>]

GO

<%
 }
}
%>

ASP.NET | CodeSmith | Dina | T-SQL
Monday, March 31, 2008 7:09:06 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, March 30, 2008

After generating all CRUD procs with several different naming prefixes, my database was looking messy. So I knew what I wanted to produce but I needed to get rid of all these other procs. So how to quickly drop all the procs. Wayne said he had a codesmith template for it but I couldn't wait. I google'd and found another person that had the same problem after a heavy CodeSmith NetTiers session. His method was not too different from my post from yesterday. I did my final gen of procs via NetTiers but instead of going into the database, sent them to a file. I opened the file to find the following code which should have been both obvious in that NetTiers would need it and where I should look for it:

BEGIN

DECLARE @procedureName SYSNAME

DECLARE c CURSOR FOR

SELECT name FROM sysobjects WHERE type = 'P' AND objectproperty(id, 'IsMSShipped') = 0

AND name LIKE 'NetTiers_%' AND name NOT LIKE 'WW_{0}_%'

OPEN c

FETCH NEXT FROM c INTO @procedureName

WHILE @@FETCH_STATUS = 0

BEGIN

EXEC('DROP PROC ' + @procedureName)

FETCH NEXT FROM c INTO @procedureName

END

CLOSE c

DEALLOCATE c

END

 

Sunday, March 30, 2008 7:02:01 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Saturday, March 29, 2008

In Sql server query window, execute query that selects all stored procedures with the prefix you want (such as procedures that start with 'cust'):

SELECT 'DROP PROCEDURE ' + Name FROM sys.objects

WHERE type in (N'P', N'PC')

and name like 'cust_%'

 

Right-click the query window and set results to text. This gives you a results window with a single column of drop prodecures. Select all the text, copy to a new query window and execute.

Saturday, March 29, 2008 8:12:22 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, March 28, 2008

After using NetTiers for a couple of weeks now, here are some suggestions for usage:

1) Use NetTiers like any third party library. Build it and include the libraries. Do not alter code inside generated libraries unless mission critical. I also use the Microsoft.Patterns library. They ship the code but I don't alter it, I just use the built libraries. 

2) Prefix the library namespace with NetTiers so that the generated libraries look like NetTiers.Entities, NetTiers.Data, etc.

3) If you use NetTiers to generate your CRUD, set the ProcedurePrefix value to NetTiers_. When you are looking through a million procs, it easier to pass a whole section based on alphabetical sorting. If you use AspNet Membership, you will be accustomed to this naming schema as those procs are prefixed with aspnet_

4) If you create your own procs, prefix those procs to something that you won't confuse with any other library's procs, such as 'cust' for custom. Of cource, IncludeCustoms is set to true and CustomProcedureStartsWith should be set to 'cust_{0}_' so that a table name of Profile should have a custom proc of cust_Profile_SelectAll.

5) While still getting your template settings figured out:

  • Don't set ExecuteSQL to true until you have tested your generated SQL and looked through what was created.
  • Set LaunchVisualStudio to true and save yourself a few clicks.
  • Set ViewReport to false. You don't need another browser to open while you are still figuring out your templates.

6) Build the Web Service and the Admin site. Even if you don't plan to use AJAX or you have your own admin pages already built, these are just more examples of NetTiers code usage. Then when you need a data backdoor or quick AJAX, you are that much closer.

7) NetTiers documentation suggests using DeepLoad to get to a related table via FK. I can see how this would be used in their example of list of Orders in a grid and you also want to display the Customer's Name in the grid. What if you had a table of ProfileItems and a table of UserProfileItems and you wanted a list of all the ProfileItems in a grid with this user's settings? With the NetTiers usual get based on FK from either table, you won't get the grid I want (right?). So in that case, I'll create a custom proc with the proper bind.

Friday, March 28, 2008 8:03:23 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, March 27, 2008

I have a table with two FKs. NetTiers creates a stored proc for the PK as well as a stored proc for each FK however it doesn't create a stored proc that uses both FKs as the IN params. So I need to create this in a way that NetTiers can discover it and build the code objects to support it.

First I have to create the stored proc with a discoverable name. This requires several settings in the NetTiers template. First, that I want custom stored procs discovered so IncludeCustoms=true. Second, I want any stored procs to have a naming prefix so ProcedurePrefix=usp. Third, I need to handle the actual name of the stored proc. NetTiers uses discovery based on a template where the zeroth parm is the table name and the first parm is the Procedure Prefix so CustomProcedureStartsWith={1}_cust_{0}_. The remainder of the stored proc name is irrelevant but what is returned is very important. I usually return all columns which is NetTiers default object handling. If I choose not to include all columns, I would have to deal with an IDataReader or a DataSet.

If all the other stored procs and NetTiers code has been generated and you only new a few stored procs to be discovered, make sure to set ExecuteSQL=false and SourceTables=(only immediate tables.)

Once you generate your objects, you can verify the stored proc was discovered by looking in the Data layer in the base directory for the TableNameProviderBase.generatedCore.cs in the Custom Methods region.

Thursday, March 27, 2008 9:00:03 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, March 26, 2008

I've been stuck in build hell for a week but now back to code. I want data that would normally be a JOIN between two tables. It's a join between ProfileProperties and UserProfileValues. But since I'm using NetTiers for my middle tier and I just want to get going, I'm writing a subpar GridView. The first column is pulled from a select of all profile properties provided by my ProfileDataSourceObject given to me by NetTiers. The second column is a function with a param of the profile property. The function grabs the user from the context and the profile property from the param, then determines what (if any) value has been set. This is not how I should do things. And since I usually don't do it this way, I'm sort of having to relearn some aspx syntax on how to do this.

I much prefer to have SQL return this data and just format it in the GridView. SQL doesn't change everytime Microsoft releases a new version of Visual Studio.

How would you do this?

 

Wednesday, March 26, 2008 7:30:31 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, March 25, 2008

Building Separately

Building the NetTiers projects are getting tedious inside my main web app solution. I'm now building them separately and just moving into my main solution as references to each project. While I'm making so many database design changes, that is the best option. When the table designs and relationships are in place, I may move the .NetTiers projects back into my main solution.

Table Standards

One of my tables had the 'name' column as the last column as opposed to the column immediately following all the id,pk,fk columns. NetTiers decided only the next column after the id,pk,fk must be the most meaningful. It used this column which was not the name column but some non-determining column as the value for drop down lists in it's web admin site. So for everytable who had this table as a fk, this non-determining column populated as drop down list. So I had to change that in the database then regenerate the NetTiers projects.

NetTiers Admin site not converting to web app

This seems to be a common problem. One googled answer said to rebuild the project twice in a row and the conversion would succeed. I don't know what I did but when I selected the Admin folder and choose convert, I got a bogus error. Then I converted each file individually, and it succeeded.

NetTiers Admin Quick Look

The NetTiers CodeSmith templates create an admin site  (if you configure it to). Here is what a couple of the pages look like:


Tuesday, March 25, 2008 7:30:18 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, March 24, 2008

Apparently, Source Safe and Visual Studio have to have the projects as sibling nodes both on the hard drive and in source safe. The source safe names must match the Visual Studio project names. So after dinking with both to try to get them to talk to each other, I scraped my current visual studio node and reorganized my hard drive directories so that all projects are siblings and the solution files are in the parent directory.

Then I tried to tie Visual Studio to Source Safe by hand. Since it still didn't work, I renamed my visual studio parent node just to save it instead of deleting. Then I had the Visual Studio solution add all the projects to source safe. This is definitely not the recommended method but everything is still small.

One of these days, I just code. And code. And code.

 

 

Monday, March 24, 2008 8:16:21 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |