Sunday, September 30, 2012

ObjectDataSource has no values to insert. Check that the 'values' dictionary contains values

The Gripe
"ObjectDataSource 'odsNameHere' has no values to insert. Check that the 'values' dictionary contains values"
This runtime error is quite confusing and obnoxious to say the least. You can't debug it the normal way because your code behind will not hit any breakpoints at all (or at least any relevant ones). At this point anyone would be quite upset, because the next question to yourself is, "@#$! Great! What the hell do I do now?"

The Gotcha
Unfortunately this error could have happened for any number of reasons, but the culprit that I find normally is that my aspx file where the Object Data Source's (ODS) target control (GridView, DetailView etc...) is located has an inappropriately used Bind(...) or Eval(...) method, or a Bound Field that must be turned into a Template Field for any variety of reasons.

The Short Answer
I can't say this will always be the solution, but the worst case scenario fix is to fully implement a Template Field for all fields and use Bind(...) for all of the sub templates.

Example:
<asp:TemplateField HeaderText="Name">
 <ItemTemplate>
  <asp:Label ID="lblName" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
 </ItemTemplate>
 <EditItemTemplate>
  <asp:TextBox ID="txtName" runat="server" Text='<%# Bind("Name") %>'></asp:TextBox>
 </EditItemTemplate>
 <InsertItemTemplate>
  <asp:TextBox ID="txtName" runat="server" Text='<%# Bind("Name") %>'></asp:TextBox>
 </InsertItemTemplate>
</asp:TemplateField>

I would like to guarantee that this will always fix this problem, but I can't. So far in my experience though, this has worked. My ODS is linked directly to a business object and I let it handle all CRUD operations.

The Long Answer
This is a big can of worms to get into, essentially the problem is the usage of Bind(...), Eval(...) and missing template tags (Item, Edit, Insert, Footer, Header).

Bound Fields
Before jumping into all of this, I would just like to say that Bound Fields are great - but they are very limited. I like using Bound Fields initially when implementing something and later I generally turn them into Template Fields (using the WYSIWYG editor). Bound Fields are nice because they encapsulate all of the basic template views (Item, Edit, Insert). This is convenient until you decide you need to add formatting to your fields. So really, Bound Fields are only really good for Read Only data or very plain data - if everything is a text field for example.

Template Fields
Template Fields are great because they give you a lot of flexibility to design exactly how you want your fields to look in all scenarios. They do have very silly limitations, such as adding formatting to a field. Let's use an example to explain this - think of a Template Field that is supposed to represent a currency and you format it using "c0" which will make your field look like this: "$1,000". Now as long as you don't intend on editing or inserting this data, you are fine - there is nothing more you have to do - in fact you might as well use a Bound Field. The problem occurs when you need to edit and insert data. Now you cannot have that formatting for your Edit or Insert fields (or Modes).

//This will only work in Read Only situations - if you intend on this field existing
//along with Edit and Insert modes while using an ODS - expect problems
<asp:TemplateField HeaderText="Price" HeaderStyle-HorizontalAlign="Right">
 <ItemTemplate>
  <asp:Label ID="lblPrice" runat="server" Text='<%# Bind("Price", "{0:c0}") %>' style="float:right;"></asp:Label>
 </ItemTemplate>
        //Notice the lack of Edit and Insert templates
</asp:TemplateField>

Let's assume that same field is read only - you won't allow it to be edited or inserted - this is a derived field of some kind. Well ASP.Net doesn't care, if you don't provide an Edit or Insert Template, but you intend on using Edit and Insert modes for your control - then you will get conversion errors (which are annoying). Going back to the same example, during an Edit "$1,000" cannot be converted to a decimal value of "1000M" (or "1000D" for VB.Net) you will get an error because of the "$" sign being part of the string. The same problem will happen in the Insert Scenario, blank cannot be converted to a decimal using the stock methods. Convert.ToDecimal("") will throw an exception.
//If this field is intended to be read only, but the control is going to use 
//Edit and Insert modes - then in some cases you have to populate the field 
//for each of the modes or risk running into problems.
<asp:TemplateField HeaderText="Price" HeaderStyle-HorizontalAlign="Right">
        <ItemTemplate>
  <asp:Label ID="lblPrice" runat="server" Text='<%# Bind("Price", "{0:c0}") %>' style="float:right;"></asp:Label>
 </ItemTemplate>
        //During Edit Populate it - but hide it
 <EditItemTemplate>
  <asp:TextBox ID="txtPrice" runat="server" Text='<%# Bind("Price") %>' Visible="false"></asp:TextBox>
 </EditItemTemplate>
        //During Insert Populate it - but hide it
 <InsertItemTemplate>
  <asp:TextBox ID="txtPrice" runat="server" Text='<%# Bind("Price") %>' Visible="false"></asp:TextBox>
 </InsertItemTemplate>
</asp:TemplateField>

The most ridiculous part of all of this is the above is not always true. It is the safest thing you can do though to avoid the error of topic. To reiterate, you should be able to avoid the error of topic if you fully implement your template field. This is (mostly) true for all cases. If your field is supposed to be hidden, read only or fully malleable. I have had this problem show up, what I would consider, randomly. It is not consistent.

I have some controls, in the same project, that share the same types of fields, but I have to template those fields differently depending on the control for some reason. I think most of these problems arise because an ODS is being used. If this was separate from an ODS, then most of these problems could probably be avoided.

Saturday, September 29, 2012

Common Base Class Work Around for Page and UserControl

The Gotcha
This is a really sore subject for me because I have tried finding a unifying factor for both sets of objects, but the answer I have come up with is - there is no unifying factor. I have read posts of people coming up with ways to have a single base class for both pages and controls - but it was a very over complicated approach and they didn't post how to do it anyhow.

http://stackoverflow.com/questions/7840706/how-to-make-a-base-class-for-both-page-and-usercontrol

I followed the advice in the above link and I have decided it is the best approach (at least for me) to follow.

The Approach
When creating a new web app from scratch, I highly recommend almost all of your page and control code behinds inheriting from a base class. The problem obviously is when you need to have code available to both base classes to do something rudimentary and basic. I recommend having the following components:
  1. Page Base Class
  2. Control Base Class
  3. Static Class that has extension and static methods in it that both Base Classes will be using. This way you don't duplicate any code.
  4. Interface for the above classes. It is not fun to maintain, but it guarantees that the implementations and signatures being used are identical for both classes.
The following is an example of the implementation. These are methods I use because they make my life easier for doing redirects and constructing URIs in the code behind. Feel free to use them.

Pages
//PageBase - The base class for all aspx pages
//ICommonPageMethods - The interface that must be implemented 
//                     in order to use the common methods safely
public class PageBase : System.Web.UI.Page, ICommonPageMethods 
{
 #region ICommonPageMethods Members
 public void RedirectToPage(string uri, bool endResponse = false)
 {
  Response.RedirectToPage(uri, endResponse);
 }

 public void RedirectToPage(string uri, string queryStringParameters, bool endResponse = false)
 {
  Response.RedirectToPage(uri, queryStringParameters, endResponse);
 }

 public string AddQSP(string key, object value)
 {
  return PageExtensions.AddQSP(Server, key, value);
 }

 public string AddQSP(params object[] values)
 {
  return PageExtensions.AddQSP(Server, values);
 }
 #endregion
}

Controls
//ControlBase - The base class for all ascx controls
//ICommonPageMethods - The interface that must be implemented 
//                     in order to use the common methods safely
public class ControlBase : System.Web.UI.UserControl, ICommonPageMethods 
{ 
 #region ICommonPageMethods Members
 public void RedirectToPage(string uri, bool endResponse = false)
 {
  Response.RedirectToPage(uri, endResponse);
 }

 public void RedirectToPage(string uri, string queryStringParameters, bool endResponse = false)
 {
  Response.RedirectToPage(uri, queryStringParameters, endResponse);
 }

 public string AddQSP(string key, object value)
 {
  return PageExtensions.AddQSP(Server, key, value);
 }

 public string AddQSP(params object[] values)
 {
  return PageExtensions.AddQSP(Server, values);
 }
 #endregion
}

Static Class
/// 
/// All of the methods here are meant to be used in conjunction with a Page Base or a Control Base.
/// Common methods for both Pages (aspx) and Controls (ascx).
/// 
public static class PageExtensions
{
 public static void RedirectToPage(this HttpResponse r, string uri, bool endResponse = false)
 {
  r.Redirect(uri, endResponse);
 }

 public static void RedirectToPage(this HttpResponse r, string uri, string queryStringParameters, bool endResponse = false)
 {
  if (!string.IsNullOrEmpty(queryStringParameters))
  {
   if (!uri.EndsWith("?") && !queryStringParameters.StartsWith("?"))
    uri += "?";

   uri += queryStringParameters;
  }

  r.Redirect(uri, endResponse);
 }

 public static string AddQSP(HttpServerUtility s, string key, object value)
 {
  return key + "=" + s.UrlEncode(Convert.ToString(value));
 }

 public static string AddQSP(HttpServerUtility s, params object[] values)
 {
  if (values.Length.IsOdd())
   throw new Exception("Parameters provided must be an even number! Key Value Pairs.");

  StringBuilder sb = new StringBuilder();

  for (int i = 0; i < values.Length; i++)
  {
   sb.Append(values[i]);
   sb.Append("=");

   i++;

   sb.Append(s.UrlEncode(Convert.ToString(values[i])));
   sb.Append("&");
  }

  sb.TrimEnd("&");

  return sb.ToString();
 }        
}

Interface
//This interface will ensure that you keep your method definitions/signatures the same.
//I can't say that this is absolutely necessary - but it is more for discipline to
//make sure that you don't alter the method for one base class versus the other.
//It is easier to just play it safe and implement this interface.
public interface ICommonPageMethods
{
 void RedirectToPage(string uri, bool endResponse = false);
 
 void RedirectToPage(string uri, string queryStringParameters, bool endResponse = false);
 
 string AddQSP(string key, object value);
 
 string AddQSP(params object[] values);
}

Wednesday, September 26, 2012

Flottery: Florida Lottery Checker

I finally published my first Android Application... It was not easy to do, it was actually quite torturous. This experience started off as a fun and what I thought would be a delightful project, into a very disheartening, taxing and confusing experience. There will be another post to follow soon explaining the difficulties.

Anyhow, here is a link to my app for those that are interested just click on the giant icon:


I am building a support page which can be seen on the top right of my blog for all DyslexicApps (this is a play on my handle) that will be published.

Saturday, September 22, 2012

How to Make Your Recycled Printer Cartridge Work Flawlessly

Here are some very easy to follow steps to make ANY Recycled Printer Cartridge work flawlessly:
  1. If you took the newly purchased Recycled Cartridge out of its box, then neatly put it back in the box as you found it upon opening it.
  2. Find your receipt. If you can't find it don't worry it won't matter.
  3. Go back to the store where you bought it (I went back to Office Depot).
  4. Go to the person in charge of ink and tell them you want to exchange your Recycled Cartridge for a Brand New Brand Name Cartridge because when you tried to use their Recycled Cartridge it stopped working after 1 print job and didn't even complete the job.
  5. The person behind the counter will mutter behind their breath that you have to remember these are recycled blah blah blah - just ignore the guilt trip.
  6. Pay the extra money you should have paid before for the name brand cartridges.
  7. Go back home and install the name brand cartridge that will not fail after the first print.
  8. Your Recycled Cartridge now works FLAWLESSLY.
The Gotcha
I made this mistake the other day again. I waited about 10 years to see if these recycled cartridges would get any better, but guess what? Even though the cartridge has ink in it and they don't seem to leak like they used to, the contact pads on the cartridge are not replaced and are worn out to hell. I think that is the epitome of the problems with Recycled Cartridges.

Think I am making it up? Take a peek at the review of the cartridge I bought for a client:
http://www.officedepot.com/a/products/324945/Office-Depot-Brand-OD222-HP-22/#reviewTab

I wish I would have read that first before buying it and having to follow the steps I outlined above.

Screen shot from Office Depot Website
But... What about the Environment?
Okay, think about it this way. Which is worse? People going to the store to buy cartridges once or going to the store to buy cartridges twice because you have to return the crappy recycled cartridge? I wasted time and gas to go help a client with her printer because of this twice. I drove 12.4 miles twice because of this cartridge. That is a total of 24.8 miles to change a printer cartridge? Is that worth the emissions?

So what I am saying ultimately is, until they fix these defects, don't bother with these recycled cartridges, they are a waste.

Lastly, I am sure there are some recycled cartridges that are better than others; for example I have used recycled toner cartridges and I have never had a problem.

Friday, September 21, 2012

ASUS Com Service (atkexComSvc.exe) Memory Leak Work Around

The Problem
So I have noticed after leaving my fairly new PC on (only about 6-9 months old now) for about a week, I was losing a tremendous amount of memory and I couldn't account for where it was going. I currently have 8GB of RAM - which I will soon be upgrading to 24 GB purely for vanity reasons - and I noticed my system was using 6/8 GB of RAM! This is shocking because all I have been doing was development work, nothing major. So even after killing all of my development related programs (VS, SSMS, SQL Server, Millions of Chrome Windows, Snaggit etc...) I was still up to about 4-5GB which is incredibly unusual.

After some investigating in the task manager, I realized I wasn't showing all processes from all users. After ticking that box I found my culprit, a Com Service that talks to the BIOS, provided by ASUS for my ASUS P8Z68-V GEN3 Motherboard.

The Gotcha
There is a process named atkexComSvc.exe that has a very bad memory leak. The memory leak is so bad that after a week of my computer being on it racked up about 3GB of memory. That is horrific. Still not really knowing exactly what the problem is, I restarted my computer and problem solved. However restarting your computer isn't something you want to realistically do every day so I have a temporary work around for this minor annoyance.

Currently only using about 6.7 MB, wait about 20 minutes and it will be 12 MB...
The Solution
Well since this process is running and you know you didn't start it, that means it runs automatically at start up and since it ends in Svc, we can assume it is a Windows Service, of course not all windows services end in Svc... Anyhow, open up your Windows Services (Control Panel > System and Security > Administrative Tools > Services Shortcut) and search for what you see in the image below:

Highlighted in blue is the name of our Concern "ASUS Com Service"
If you are currently suffering from System Memory Loss from this service, go ahead and restart it. You can right click and select restart or use the menu on the left shown in the image above.

To verify that we have the right windows service (and process), right click on it and select "Properties".

Found the culprit process's Windows Service
So as you can see this service is automatically started and it spins up the process named "atkexComSvc.exe" as shown before in the Windows Task Manager. Well since all we can do right now to alleviate the memory leak is to restart the service, let's just do this every day automatically at about 5 AM. Sound good to you?

Notice the path to the service is conveniently shown, you can go there to do the next few steps.

Creating a Windows Task in Task Scheduler
So this is going to require a batch file, there are a number of ways of doing this, I just like using batch files for their simplicity.

Batch File Code
ECHO Stopping atkexComSvc.exe - ASUS Com Service
NET STOP "ASUS Com Service"
ECHO.
ECHO Starting atkexComSvc.exe - ASUS Com Service
NET START "ASUS Com Service"
REM PAUSE

Go ahead and throw that code into a file, name it whatever you want as long as the file extension ends in ".bat" so for example, I named my file "Restart Com Service.bat". You can double click on the file to execute it which is convenient at times for quick execution. The last line of the code is commented out by using the keyword REM. Only enable PAUSE (by removing the word REM) if you are debugging the script, otherwise your batch file's console window will show up at 5 AM and stay there until you press any key to make it go away.

I put this file into the same folder as the Com Service, not necessary, but I think it makes the most sense so you know where it is.


The location of the process (for me anyhow) is located here: C:\Program Files (x86)\ASUS\AXSP\1.00.14


Open up Task Scheduler (Control Panel > System and Security > Administrative Tools > Task Scheduler Shortcut) and you should see an ASUS folder. If you don't it doesn't matter, but just for organization I would add you task there. Right click on empty space and select Create Basic Task. Follow the prompts and when it asks you for the program/script, browse to the batch file we created earlier.

If you want to test your task after creating it, right click on it and select "run" from the context menu.

Don't worry if the service complains that it can't stop or anything - it might be in the middle of something OR if you already restarted it once and you are trying to restart it again, it might refuse you the second time. I encountered that problem. Either way the goal was to just make it empty out its memory allocations, so it could start filling up all over again.

Enjoy.

PS: If ASUS doesn't fix this soon, I think I am going to decompile the service and look for the problem myself. This is just ridiculous. Hopefully they fix this soon.
UPDATE: 01/13/2013 - I couldn't decompile this executable. It is not written in .Net because when I used Just Decompile from Telerik it wouldn't work and I tried a C/C++ decompiler but it blew up when I tried to use it. So I guess I will just try the old fashioned way, I will make a support ticket for this when I get around to it. If anyone knows how to decompile this executable I'd appreciate a clue.

Thursday, September 13, 2012

How to get rid of the black border on HDMI output on your AMD Radeon HD 7850

This was more of a pain in the ass than it was Obscure, more of a Gotcha, but not really since there is indeed a solution, you just need to dig for it and it isn't too obvious due to wording.

I have the AMD Radeon HD 7850 and it is a really good card, although discontinued recently. I used HDMI for my second monitor, I don't game on it so it is great for just viewing normal things. I use DVI for my primary monitor. Anyhow, setting up the HDMI monitor was harder than it needed to be. I swore my card was dead for a while when I tried getting it to work because all I got was a black screen. Unfortunately I don't remember the specifics of it, otherwise I would post about it.

HDMI Output Gotcha
All I can say is, if you intend on using an HDMI monitor with your PC, plug it in AFTER windows has booted and you are logged in! Otherwise you might just get a black screen when you get to windows. Your mouse might be active, but that's it.

How do I get rid of that damn black border around my screen?
This is ridiculous, but believe it or not it is a setting. I am sure there is a good reason for it, but why not make the default fill up the screen, not the reverse? So that black border around your screen has everything to do with your "Scaling Options".

Here is a screenshot of what I am talking about:


  1. You have to open up the Catalyst Control Center. You do so by right clicking on an empty spot on your desktop and clicking on "Catalyst Control Center" in the context menu (should be at the top).
  2. Go to the "My Digital Flat-Panels" section
  3. Click on "Scaling Options (Digital Flat-Panel)"
  4. Move the Slider over to the right completely until it says 0% (Overscan max I suppose). You will see your screen size change as you do this.
  5. Apply your changes and exit.
Enjoy!

Changed Blog Background

I changed the background of the blog because I think it is easier on the eyes. I have a problem staring at lines that are too close together like the last background. I apologize if that was hard on the eyes for anyone - this new background should even things out nicely.

I will be writing an article soon about office lighting, backgrounds, color and your eyes. Things people take very lightly, but should be more serious about. A preview of what I am referring to is - stop using white backgrounds especially if you wear glasses with a crappy prescription like mine.

Tuesday, September 11, 2012

How do I consolidate my student loans?

This is an unclear and scary subject for most people exiting college and being thrown into the woes of the work force. I say woes because after my first 4 months on my first job out of school I was laid off - that is hardly fair - but I survived even with my loans on my back.

The Debt you Earned
If you were like me when you were in college you probably racked up a nice chunk of change in student loans because you had no choice. The government told you that your parents were supposed to contribute an impossible amount of money to your education and when you showed your parents your EFC they just laughed at you. So while you were in school, every semester you took out more loans, those loans were never consolidated because of faulty reasoning in my opinion, but hey, beggars can't be choosers. Those loans were all accruing interest with the exception of your Federal Subsidized loans if you had any. Do not be fooled though Subsidized loans begin to accrue interest as soon as you reach your repayment period after your 6 month grace period.

The Shocker
Now you are out of college and it is time to pay back. What's this? An unspeakable amount of money you are expected to pay every month after your 6 month grace period?! Oh jimeney Christmas! You knew you had to pay, but not this much!

Consolidation to the Rescue
Well that is where consolidation comes into play. You really don't want to pay off 10 or 20 small loans, you want to pay off 1 or 2 consolidated big loans. Why not just 1 loan? Ah, you see that would be too easy, there are different loan types that prevent that from being a reality, which in my opinion doesn't make much sense depending on the loan.

Loan Types and Consolidation
As you will quickly learn, the different types of loans that you have can or cannot be consolidated. The basic rule seems that Loans of the same type can be consolidated and nothing more.
  • Private Education loans cannot be consolidated together with Federal Loans - this makes sense to me. I have a Private Education loan that has a variable interest rate, it cannot be consolidated together with my fixed rate Federal Loans. The main reason (I think) they can't be consolidated is because one of my loans was from the Private sector and the others are from the Public sector.
  • Federal Subsidized loans cannot be consolidated together with Federal Unsubsidized loans - this makes little to no sense to me. Both my Subsidized and Unsubsidized loans have the same interest rate and are both Federal loans, in my opinion they should be consolidated, but they aren't, even though my Subsidized loan is now accruing interest just like my Unsubsidized loan. Why not just consolidate them then? No idea why they don't...
Unfortunately sense plays no part here, now it is time to pay back your borrowed money - that's all that is clear.

Interest Rates
As mentioned before, you can have different types of Interest Rates, there are two main types:
  • Fixed Rate - Fixed Rate loans have the same interest all year until they are recalculated. They can be changed when Ben Bernake farts or when congress hates you because they think cutting spending really means to raise rates on people repaying their student loans.
  • Variable Rate - These rates fluctuate often, the recalculation depends on your loan, but most of the time it is quarterly (I need to verify this). Usually these are the worst kind, but right now, since the US economy has the pulse of a Clam - you can actually rejoice a little - your interest rates are probably lower than the Federal Rates as of right now (09/11/2012) and they have been like that for a while. However, when the economy is revitalized expect your rates to shoot back up, but there is luckily a cap on how high they can go.
Okay... So How do I Consolidate my Loans?
You can attempt to go to a variety of places for your student loan consolidation. For example you can try to consolidate your loans with the people you have your loan with. However prepare yourself for them to possibly stonewall you and say something to the effect of, "We are not accepting any new applications for Loan Consolidation at this time.", which is a banks way of saying, "Sit and Spin". I had this happen to me with Sallie Mae, therefore I will shamelessly say, NEVER USE SALLIE MAE THEY SUCK. So I found myself in this predicament until I found only one place on the face on the planet that would consolidate my loans and they are named "Direct Loans" or at least they were, they recently changed their name to EdFinancial. I highly recommend EdFinancial for your Federal Loans, they do not take Private Loans, but do not fear there is another company that you can use for your Private Education Loans named American Education Services. Truth be told I didn't actually seek AES out, they found me and bought my loan from JP Morgan Chase because, just like Sallie Mae told me to sit and spin, JP Morgan Chase had me at an alarming 11% variable interest rate.

Recap: People you can consolidate with and what for
  • EdFinancial - http://www.edfinancial.com - they will mostly take your Federal Loans ONLY - They will NOT take Private Education Loans.
  • American Education Services (AES) - http://www.aessuccess.org/ - they will take your Private Loans and possibly others.
I trust both of those companies because they are Government run or backed.

My Real Federal Loan Example
I took my 10 or so small loans from Sallie Mae which was a monthly payment of $425 at a different interest rate per loan over to what was known as Direct Loans at the time and they consolidated me down into two Loans, both at 6% initially. I was then paying $230 per month. Big $195 dollar difference there huh? If you sign up for automatic bill pay, it drops the interest down to 5.75% which is indeed significant (-0.25%). I now have two main Loans, one Subsidized and one Unsubsidized, but don't be fooled by the names they both accrue interest. The government just refuses to consolidate them together even though they have the same interest rate...

My Real Private Education Loan Example
So I didn't actually refinance this loan myself, it was done for me without my permission, but you know what - I am very glad it happened. AES lowered my interest rate from a horrific 11% down to 4.00-4.25%. It does fluctuate, but not too much.

Pay Off Strategies
If you are capable of doing so, enroll in the aggressive payoff schedule. This means your payments are higher, but you pay off more principal each month. You want to attack your principal as much as possible. If you go for the lowest payment you not only have more payments up until the end of your scheduled loan Payment Period (10 years typically from the time you start paying not including forbearance or deferment), but you also risk paying more unnecessarily due to interest rate hikes, policy changes, your loans being sold to a crappy company etc... In other words - the faster the better. I currently pay about $300 total each month in loans, I would like to not have to do that anymore.

Advanced Payments
If you want to send in an extra amount towards your principal, DO NOT use the regular payment system they have online. You need to call your loan owner/servicer and get instructions on how to do this. If you do not call and get the specific instructions, then the payment you sent in is going to be treated as a PRE-PAYMENT which is not the same thing as paying down your loan.

The best way to look at your loans (in my opinion) is in $5,000 chunks (5K Chunks). You want to strive to pay off those chunks. Let's say you have a $30K loan, 30/5 = 6 - 5K Chunks. It doesn't change anything, but it makes the loan a little less scary because you only have to pay down six 5K loans. So if you save up some money to do this, then you will be doing double duty on your payments because between your savings and the monthly payments that you are making you will wear down those chunks to zero.

Don't go broke paying down your loans though, it isn't smart to take all of your savings and throw it at your loans, you want to have a cushion for those rainy days. It is easier to make those monthly payments, rather than pay it all off and then possibly lose your job unexpectedly with no money to fall back on.

What are Pre-Payments
Pre-payments are just like they sound, you just paid in advance so you don't have to pay later. Basically there is a credit on the books, so your following monthly balance will be paid off and you will most likely receive a bill of zero dollars for that month. This can be confusing for a lot of people, it was confusing to me because I made this mistake. It isn't very intuitive, just like companies not consolidating Sub and Unsub loans after entering the payment term...

Conclusion
Loans, much like credit cards, are not that scary if you understand them. Remember you got this loan for a reason, so now you have to pay it back that was the agreement. The faster you pay it down the better because you will pay less in interest and you can get your disposable income back into your pocket.

Monday, September 10, 2012

GridView does not have a default Insert Support

Here is a fun fact for you. The ASP.NET GridView control does not have default Insert Support for your objects, even if you are using the "InsertItemTemplate" tag, it doesn't matter! That template is apparently there for other controls that can support it - I am not sure who or which those are. So if you were like me, trying to find a way for the Insert template to just start magically working, don't waste your time. You must create this functionality yourself (OH HAPPY HAPPY JOY JOY!).

It seems like there are only a few controls that support this, like the DetailView control which is excellent for individual records.

Otherwise you will be resigned to using a method like the one described in this article here:
http://weblogs.asp.net/manojkdotnet/archive/2009/10/11/insert-update-and-delete-using-grid-view-and-objectdatasource.aspx

A Few Gotchas to Look Out For
  1. As mentioned above, don't bother with the <InsertItemTemplate /> tag, much like the goggles, they do nothing! If you added them already, don't delete them, just do a find and replace (Ctrl + H) on them and replace it with "FooterTemplate" because you are going to need it anyhow.
  2. As much as it pains me to say, any <asp:BoundFields /> you want to be able to insert will have to be converted to <asp:TemplateFields />, the good news is this is easy to do with the page Designer tool. I suggest using it as it provides a link you can click that does this for you. However once done, it will not provide an option to undo it.
  3. If you are having trouble making those <FooterTemplate /> fields show up, it is because you have to enable the ShowFooter property in the GridView itself.
  4. You will have to include a column that will house a button just for inserting new rows.
  5. You will have to wire up an event to that button and handle the creation manually because your object data source (ODS), if you have one, will not handle it automatically.
  6. After hitting the button, your grid will not refresh itself unless you call your grids DataBind() method.
  7. If your grid is empty, your footer will not show up, therefore you cannot add any new records. I suggest making sure that you check your data source before it reaches your ODS or GridView so that this doesn't happen. If you have zero rows, add 1 bogus row and just make sure the user cannot add or edit it.
Here are more links that helped me figure this all out:
Have fun I know I did...

My Example Html

<asp:GridView ID="gvw" runat="server" 
            EmptyDataText="There are no Objects to display."
            AutoGenerateColumns="False" 
            ShowFooter="True"
            DataSourceID="ods"
            onrowcommand="gvw_RowCommand" >
    <Columns>
        <asp:TemplateField HeaderText="ObjectID" InsertVisible="False" Visible="False">
            <ItemTemplate>
                <asp:Label ID="lblObjectID" runat="server" Text='<%# Bind("ObjectID") %>' />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Amount">
            <ItemTemplate>
                <asp:Label ID="lblAmount" runat="server" Text='<%# Bind("Amount", "{0:n}") %>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtAmount" runat="server" Text='<%# Bind("Amount", "{0:n}") %>' Width="100px"></asp:TextBox>
            </EditItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="txtAmount" runat="server" Text='<%# Bind("Amount", "{0:n}") %>' Width="100px"></asp:TextBox>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Series">
            <ItemTemplate>
                <asp:Label ID="lblSeries" runat="server" Text='<%# Bind("Series") %>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtSeries" runat="server" Text='<%# Bind("Series") %>' Width="100px"></asp:TextBox>
            </EditItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="txtSeries" runat="server" Text='<%# Bind("Series") %>' Width="100px"></asp:TextBox>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Notes">
            <ItemTemplate>
                <asp:Label ID="lblNotes" runat="server" Text='<%# Bind("Notes") %>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtNotes" runat="server" Text='<%# Bind("Notes") %>' Width="100px"></asp:TextBox>
            </EditItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="txtNotes" runat="server" Text='<%# Bind("Notes") %>' Width="100px"></asp:TextBox>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowHeader="false" 
            InsertVisible="False" HeaderText="" />
        <asp:TemplateField ShowHeader="False" HeaderText="">
            <FooterTemplate>
                <asp:Button ID="btnAdd" 
                            runat="server" 
                            CommandName="Insert" 
                            Text="Add" 
                            OnClick="btnAdd_OnClick" />
            </FooterTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ods" runat="server"
    TypeName="Namespace.ClassName" <!-- Always use the fully qualified class name for your class that has your methods in it --> 
    DataObjectTypeName="NameSpace.ObjectName" 
    SelectMethod="GetObject" <!-- Select Method in Namespace.ClassName -->
    DeleteMethod="DeleteObject" <!-- Delete Method in Namespace.ClassName --> 
    UpdateMethod="UpdateObject" <!-- Update Method in Namespace.ClassName -->
    oninserting="ods_Modification" <!-- I happen to use the same handler for all of these operations -->
    onupdating="ods_Modification"
    OnDeleting="ods_Modification" >
    <SelectParameters> <!-- my select method has a required parameter, it gets its value from the QueryString -->
        <asp:QueryStringParameter DefaultValue="0" Name="ObjectID" 
            QueryStringField="ObjectID" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

My Example Code Behind
I am only going to show the event handler for btnAdd_OnClick because everything else is not completely relevant right now (I will be writing a new article about it soon). I will say however that if you are not showing your column that has the ID in it (Visible="false") then your ODS's base object will not have that ID and your update and delete methods will fail.

protected void btnAdd_OnClick(object sender, EventArgs e)
{
 ObjectName obj = new ObjectName();

 //Load your new object with values from the footer
 obj.Amount = Convert.ToDecimal(gvw.FooterRow.GetTextBox("txtAmount").Text);
 obj.Notes = gvw.FooterRow.GetTextBox("txtNotes").Text;
 obj.Series = gvw.FooterRow.GetTextBox("txtSeries").Text;

 //This is the insert method that the ODS could not use
 Namespace.ClassName.InsertObject(obj); 

 //In order for your GridView to refresh itself you must do this step
 //otherwise it will feel like nothing happened when it really did
 gvw.DataBind();
}

Easy Way to Start/Stop SQL Server on a Multipurpose Machine

I have been doing a lot of development on my gaming machine and as all gamers know, you want to have as much free RAM as humanly possible while playing games. I close all open applications, but what doesn't help is having running services in the background doing nothing. A good example is SQL Server. So in efforts to free up more RAM while playing games I wrote the following batch files which I run as needed:

Start Script

@ECHO OFF

ECHO Starting all SQL Server Services
ECHO .
NET START "SQL Server VSS Writer"
ECHO .
NET START "SQL Server (SQLEXPRESS)"
ECHO .
NET START "SQL Server Browser"
ECHO .
ECHO All Services Started
PAUSE

Stop Script

@ECHO OFF

ECHO Stopping all SQL Server Services
ECHO .
NET STOP "SQL Server (SQLEXPRESS)"
ECHO .
NET STOP "SQL Server Browser"
ECHO .
NET STOP "SQL Server VSS Writer"
ECHO .
ECHO All Services Stopped
PAUSE

You can add any other service to this list, just make sure you know what it is that you are messing with. This is an alternative to going into the Services GUI and doing it one by one. Also please note that if you are not sure what your SQL Server Service instance is named, just look in the Services GUI to find out. I happen to be running the express edition hence the naming.

Just a quick tip.