In the last post, I wrote about LAF, difference between LAF and unit test, controller test, etc. Now we are going to get into on how to user LAF, especially in ASP.NET MVC project.
In my demo project I have a Customer list (it can be any list) that looks like this:
So I want to test all web functionality that an end user will and can possibly do. How do I do it with LAF?
First, create a web application to run your LAF project. ou can follow the instruction to do that here.
After you got that setup, create a class file and start writing tests. So in my example, I want to tests for simply displaying the list, sorting, paging, clicking "New", clicking "Select", and clicking "Delete".
OK, let's begin with displaying the list:
So a very simple test where basically I navigate to the Customer page and make sure it displays my table. I can do additional checks like whether there are 10 rows in my list, whether the first record is correct, etc. We will see how to do those things in the following test examples.
[WebTestMethod]
public void FullList()
{
HtmlPage page = new HtmlPage("");
// navigate to Customer list page
page.Navigate("/Customer/");
// Verify search result
HtmlTableElement gridView = (HtmlTableElement)page.Elements.Find("CustomerListingTable");
Assert.IsNotNull(gridView);
}
So, how about testing Sorting functionality? In our list, a user should be able to click on the header and sort the data based on that field ascendingly and then descendingly.
What happen in the code above is quite simple; after navigating to the Customer list page, the test verify whether the grid/table exists. After that, it navigate within the table and click the header of the first name column (I enumerated my columns). Then I verify the result by comparing the first name data between the 1st record and the 2nd record according to the sort direction.
[WebTestMethod]
public void SortByFirstName()
{
HtmlPage page = new HtmlPage("");
// navigate to Customer list page
page.Navigate("/Customer/");
// Verify search result
HtmlTableElement gridView = (HtmlTableElement)page.Elements.Find("CustomerListingTable");
Assert.IsNotNull(gridView);
// sort by first name desc
gridView.Rows[0].Cells[(int)ColumnNames.FirstName].ChildElements[0].Click(WaitFor.None);
// wait for my jQuery ajax
System.Threading.Thread.Sleep(1000);
// verify
Assert.IsTrue(gridView.Rows[1].Cells[(int)ColumnNames.FirstName].GetInnerText().CompareTo(gridView.Rows[2].Cells[(int)ColumnNames.FirstName].GetInnerText()) >= 0);
// sort by first name asc
gridView.Rows[0].Cells[(int)ColumnNames.FirstName].ChildElements[0].Click(WaitFor.None);
System.Threading.Thread.Sleep(1000);
// verify
Assert.IsTrue(gridView.Rows[1].Cells[(int)ColumnNames.FirstName].GetInnerText().CompareTo(gridView.Rows[2].Cells[(int)ColumnNames.FirstName].GetInnerText()) <= 0);
}
Now let's test our paging. There are multiple ways to page through the data according to our list. A user can click on the page number, or click on a previous or next link, and they can do it through the top page numbers or the bottom one.
What happen on the code above is basically I queried the page number link and click it. From the default page 1, to page 2, then page 3, then page 4, to test consecutive paging. After that, from page 4 jumped to page 1, then jumped to page 3. Obviously, there are more variety of these that we can do, but hopefully you get the idea. Also, in this code, I am just testing on paging by number for if the users are just paging using the page numbers on the top. To test the previous or next link, the code should be pretty similar to this.
[WebTestMethod]
public void PageByNumberTop()
{
HtmlPage page = new HtmlPage("");
// navigate to Customer list page
page.Navigate("/Customer/");
// Verify search result
HtmlTableElement gridView = (HtmlTableElement)page.Elements.Find("CustomerListingTable");
Assert.IsNotNull(gridView);
// get the paging links
HtmlElement topPaging = page.Elements.Find("pagination-clean-top");
// verify page 1 and goto page 2
page.Elements.Find("toppage2").Click(WaitFor.None);
System.Threading.Thread.Sleep(1000);
// verify page 2 and goto page 3
Assert.AreEqual("2", topPaging.ChildElements[2].GetInnerText());
page.Elements.Find("toppage3").Click(WaitFor.None);
System.Threading.Thread.Sleep(1000);
// verify page 3 and goto page 4
Assert.AreEqual("3", topPaging.ChildElements[3].GetInnerText());
page.Elements.Find("toppage4").Click(WaitFor.None);
System.Threading.Thread.Sleep(1000);
// verify page 4 and goto page 1
Assert.AreEqual("4", topPaging.ChildElements[4].GetInnerText());
page.Elements.Find("toppage1").Click(WaitFor.None);
System.Threading.Thread.Sleep(1000);
// verify page 1 and goto page 3
Assert.AreEqual("1", topPaging.ChildElements[1].GetInnerText());
page.Elements.Find("toppage3").Click(WaitFor.None);
System.Threading.Thread.Sleep(1000);
// verify page 3
Assert.AreEqual("3", topPaging.ChildElements[3].GetInnerText());
}
- Part 1: Overview
- Part 3: Add, Edit, Delete
-- read more and comment ...
Monday, March 16, 2009
ASP.NET Lightweight Automation Framework - List, Paging, Sorting (2/3)
By
Johannes Setiabudi
@
10:14 AM
0
comments! add yours!
Not on The Menu: Quesadilla at Chipotle
Last night I went to Chipotle for dinner with my wife and son. There were like 5 or 6 people a head of me in the line - so I took my time to ponder what I want to order.
When it was about just 2 more person ahead of me, I saw the lady behind the counter did something I have never seen before in Chipotle - she put cheese on the tortilla then fold it and put it on the tortilla press/warmer.
Then the next guy - the guy who is directly in front of me - said something like this "Same thing - chicken quesadilla." After hearing that, I reread the menu on the big board again and again and again - and I was pretty sure that quesadilla was not on the menu.
So now, it was my turn to order, I ordered my half chicken and half carnitas salad and then I said, "Can I have a small cheese quesadilla for my son?" As I was expected, the lady said, "Sure. Just cheese?" and I replied back "Yes, just cheese."
As I walked down and selected my choices of salsa, sour cream, and cheese, I glanced back at the menu trying to find the word "quesadilla" - but it was nowhere to be found. Then at the cashier register, the cashier lady punched the buttons and I briefly saw that there was an entry for my small chicken quesadilla - it was also in the receipt - for $1.00. I am not sure how much the big quesadilla is or if you add meat to it.
So there you go, Chipotle has quesadilla - btw the small cheese quesadilla is great for kids!
Some Chipotle tips & tricks:
1. If you are getting a carry out, order online!
2. Instead of getting a fajita wrap, get a fajita bol WITH tortilla on the side. On the bowl, you can get extra stuff without the fear of tearing your tortilla. Plus it is not as messy and easier to bring home if you cannot finish it.
3. You can get half & half meat. So you can get chicken & steak or steak and carnitas, etc. They will charge you for the higher price ($0.50 difference I think between chicken and steak/carnitas).
4. You can get more than one type of salsa. So get corn salsa AND verde AND the hot salsa if you want - or nay combination thereof.
5. If you are ordering a salad and feel that it is kinda small - so add stuff to it (but no beans or rice). I usually add onions/peppers and salsa combination.
-- read more and comment ...
By
Johannes Setiabudi
@
7:34 AM
2
comments! add yours!
Sunday, March 15, 2009
ASP.NET Lightweight Automation Framework - Overview (1/3)
ASP.NET QA Team released the Lightweight Automation Framework on mid Feb 2009 - and I have been using it to test the project I am working on (an ASP.NET MVC project). Suffice to say that I am thrilled and having fun with it (and actually caught some bugs because of it!!).
In this post I will outline the basic of Lightweight Automation Framework (LAF) and in the following posts I will put some sample code, quirks, how to, etc.
What is Lightweight Automation Framework?
LAF is an internal test tool that ASP.NET QA team use to do regression testing on ASP.NET feature. Remember that it is a tool, so you still have to build your tests, but this framework allows you to build and run or do your tests easily and in a more comprehensive manner - and most importantly, it is automated.
How does LAF differs from regular unit test or other test project such as MVC controller tests?
LAF is a regression test tool - so it suppose to test the web application from user's perspective. This would be the tool to use to implement all your use-case scenarios testing. So the scope is much larger compared to unit test.
Another thing that we will see is that LAF actually runs as within an ASP.NET application - instead of just running/executing code. LAF will actually read and manipulate the DOM in the browser (you can run in IE, FF, Safari or Opera). So when you run a typical test in LAF, it will look like someone is running the web application in a browser and clicking this, entering data, etc etc.
This is something wonderful with LAF, since what used to be tedious and hard to be done - end user testing - now can be automated (by code).
Where can I get it?
You can download the source code in its codeplex page as well as read further about it.
ASP.NET QA Team also has a blog here.
- Part 2: List, Paging, Sorting
- Part 3: Add, Edit, Delete
-- read more and comment ...
By
Johannes Setiabudi
@
7:08 PM
0
comments! add yours!
Tuesday, February 17, 2009
Saving Money on Electricity & Gas Bills
A friend of mine just told me about his gas bill for last month - a whooping $600+. Good thing that he lives in the house with 6 other housemates and the house is also an older house - so there are probably some leaks here and there which creating more work for the heater, hence more expensive payment.
Another fellow also is paying about $150+ per month for his electric bill per month.
I used to never really consider them as a big deal until I moved into a house, got married, and had a son. My expenses are piling up and I need to tighten my budgeting and do some cost cutting. One of the first area that I was able to successfully reduce is in the area of utility bills.
My gas bill used to be about $300 during the winter months and about $70 per month for the rest of the year. Last year, I reduce my gas bill from averaging $300 per month between December to March to about $150 per month (so about 1/2 of it used to be).
So how did I do it? Here are several tips that I found to be pretty useful...
Gas
I live in a 4 bedroom house, but we in most nights we only use 2 of the bedrooms: for my wife and I, and another room for my son. We use another room as my office and the last one as a guess bedroom. So keep in mind that the suggestions below may or may not apply to you in all situations - I am just providing tips that so far have been working pretty well for me and my family.
1. Get a programmable thermostat
This may cost you between $30 to $200, depending on how fancy you want to get with your thermostat. At least get a programmable one for both heat and cold air - and can be programmed based on daily basis. Some only has weekday or weekend setting. Depending on your need, get whatever suited for you. Mine is programmable by day and it is only $40 (one of the best investment in home improvement I have made).
2. I programmed it to turn down the temperature during the day on several days of the week where nobody is at home. Do not turn your heater off, but just lower the temperature. I lower mine to 10-15 degrees cooler than the regular temperature. So when I am at home, the thermostat usually shows 72 F and ~60 F when nobody is at home. You can program it so that it goes back up to the regular comfortable temperature 30 minutes before you are back home so you will come home to a warm house instead to a cold one. Obviously you cannot consider all possibilities, but try to get the "typical" schedule - and then program them it - you can override them as necessary.
3. If you are going away for a longer period of time (like on a vacation), lower your house temperature to the upper 40s F (but do not turn off your heater) and set it to come back up when you are about to come back.
4. If your household is like mine, where we typically are only using 2 rooms at night (or less), you may want to consider buying an oil portable heater. So at night, schedule your main house thermostat to lower the temperature to the 60s F and turn on your oil heater in your bedroom(s). That way, you are only heating the necessary rooms (typically your bedrooms) and not wasting energy on other unused rooms. I usually turn down the house temperature at 9:30pm and turn on the oil heater in my bedroom around the same time. Since the heat dissipates gradually in the main house so I won't notice much difference when I am walking into my bedroom (typically around 10:30pm) where the temperature is already picked up my the oil heater. My oil heater has a timer so it shut itself down around 7am, while my main house thermostat increase the temperature of the house around the same time (up to 72 F).
5. Reduce leaks. Make sure your doors, windows, etc are not leaking. You can buy weather strips at the hardware store to stop the leaks from doors and windows.
6. Install a ceiling fan. Heat goes up and ceiling fan helps to circulate the hot air from your heater better. You do not need to do this on every room of your house, but it will be very helpful to have it in your most used rooms in the house. Secondly, during the non-winter times, it can also give you some extra breeze.
There are other things you that requires much more money, such as replacing your windows with double layer windows, installing screen doors, fixing wall insulation, etc. I am going to get into those things in this post. Another thing you can do is put on an extra layer of clothing and lower the temperature. One of my friend set his daily temperature at 68 F during the winter months - and always wear a sweater or extra layer of clothing at home. Works great for him!
Electric
The principle is no different than "gas" - less usage means less payment.
1. Change filament based bulb with CFL bulbs. They cost more to buy, but they are worthy investments in the long run. Especially if you live in a house, where there are tons of bulbs. CFL bulbs usually cost you $2 per bulb but they also last longer than filament bulbs. In most cases, your average house filament bulb is a 60W bulb. Using CFL, you can get the same brightness with just 15W - that is 75% energy saving per bulb.
2. There are some light fixtures or lights that cannot use CFL bulbs. Light fixtures with dimmers cannot use CFL bulbs. Also, some of my lights are using fluorescent lights. In those areas, I would try to find the lower energy bulbs/lights (substitute 40W fluorescent with 34W, etc). Read more about CFL bulb here.
3. Always turn-off when unused. You can get a smart switch that automatically turn off the light when the room is unused for a period of time. OR ... you can just create a good habit of turning off the light when you are not using the room. In my house a good example of this is the kitchen, where there are 4 strips or 40W fluorescent light on the ceiling - totally to a 160W energy used when it is on. You can reduce the energy usage to 0 if you turn it off. Of course this also applies to other appliances and electronics, such as TVs, computers (or you can set it to hibernate automatically), DVD players, etc.
-- read more and comment ...
By
Johannes Setiabudi
@
8:23 PM
2
comments! add yours!
Saturday, February 14, 2009
Future Quarterback?
Once sport that Jon was exposed to since early on is football. He basically grew up knowing that Ohio State is THE team in football and yelling "O-H" "I-O" is something considered to be much more precious than "da-da". His first ball is an Ohio State football and his first jacket is an OSU jacket.
Anyway, I took some pictures of him playing with buddy Andrew on Monday - and surprisingly he could hold the football correctly (most of the time) and threw some spiral several times.
So here are some pictures:
Call plays and reading defense ....
Ball is snapped ...
Fake pump to the right!
It's a Quarterback Draw!
He runs and he scores!!! Touchdown!!!
-- read more and comment ...
By
Johannes Setiabudi
@
10:45 AM
2
comments! add yours!
Tuesday, February 10, 2009
Outlook Filter/Rule to Remove Spam from YOURSELF?
My MS Outlook Exchange account is littered with SPAM - so I turned on the junk email filter on. This enables the auto rules that move "junk"-ish email into the junk mail folder. It does not move all junk email to junk mail folder but for the ones that pass through the filter I can individually right click and include them as junk, so the next time the same email address sends me anything, it will be considered as junk.
So, I am golden, right? Yes ... for a while ... until I start to get junk emails from MYSELF. I am pretty sure that my computer is clean from adwares, viruses, etc. So, it must be that the spammers have gotten my email address and they are spamming me using it. If I try to include those email in the blocked senders list, I can't - since the sender's address is my own email address. To handle this, initially I create a filter to block certain subjects (since they are all have similar subjects). This works for a while. But as time goes, I have to keep adding and adding more subjects into my rules - which becomes very large. There must be an easier way!
Here is how I solved the problem above:
I created a new rule in Outlook, and the rule is basically checking my email header. So I check for email sent by my email address but is not sent from my Exchange server and move those to junk mail folder (and stop processing any more rules). Voila! Now my Inbox is clean and I can remove my bloated "subject" rule.
-- read more and comment ...
By
Johannes Setiabudi
@
11:41 PM
2
comments! add yours!
Hot Chicken Chowder
I made spicy chicken chowder last Saturday and it turned out great. The (already awesome) original recipe is from the food network - by Paula Deen and I put my own twist into it - although the main essence is still the same.
Here are some of the changes I made:
Now here is the kicker ... it tastes even better the second day - so my advice is to make it at night and eat it for lunch the next day! Get a cuban bread and you are set!
-- read more and comment ...
By
Johannes Setiabudi
@
10:02 PM
0
comments! add yours!
Monday, February 9, 2009
Dynamic LINQ Library
Let's say you have an application that has a list page that displays a collection of records (i.e. product list)- and on this list page, you want to be able to sort based on the field headers by clicking it. If clicked again, it would reverse the sort direction/order (ascending/descending) - just like Windows Explorer.In regular LINQ - this is not so easy, since LINQ is strongly typed. So let's take a look how would we do this in regular LINQ. Getting all Products by CategoryId = 5 ordering them by SupplierId
var products = from p in Products where p.CategoryId == 5 order by p.SupplierId select p;
var products = from p in Products where p.CategoryId == 5 order by p.SupplierId descending select p;So not bad. But what if we want to sort by UnitPrice?
var products = from p in Products where p.CategoryId == 5 order by p.UnitPrice select p;How about sort by ProductName?
var products = from p in Products where p.CategoryId == 5 order by p.ProductName select p;So if we want to have an option to make our product list sortable by ProductName or UnitPrice or Supplier, we would write something like this in our code:
... var products; switch (sortfield){ case "ProductName": products = from p in Products where p.CategoryId == 5 order by p.ProductName select p; break; case "UnitPrice": products = from p in Products where p.CategoryId == 5 order by p.UnitPrice select p; break; case "SupplierId": products = from p in Products where p.CategoryId == 5 order by p.SupplierId select p; break; } ...Which is OK - but what if we have 10 sortable fields? It will be a super long code and very repetitive. So how can we solve this problem with proper refactoring while still using LINQ? This is where LINQ Dynamic Library saves the day!First of all, you need to download the library:After the file is downloaded, include the Dynamic.cs (or vb) in your project. Now everytime you want to use dynamic linq, you will need to reference the namespace System.Linq.Dynamic in your code (or you can use a using statement - or Import in vb). Now using the dynamic library, the code above can be transformed into something like this:
... var products = Products .Where(p => p.CategoryId == 5) .OrderBy(sortfield); ...It is much more concise, clean, and configurable. So there you go, LINQ Dynamic Library - extremely useful!You can learn about LINQ hereScott Guthrie has an excellent post about LINQ Dynamic Library here
By
Johannes Setiabudi
@
9:30 PM
2
comments! add yours!
Tuesday, January 27, 2009
How to Increase/Enlarge Hard Drive Space in a VM
Cannot enlarge hard drive space?
First of al, to enlarge your hard drive space, you will need to turn off the VM. Highlight your VM and under disk, click EDIT and there should be a link to enlarge your drive space. This option will be disabled if you have taken snapshots of your VM. So in this case, delete/collapse the snapshots and then enlarge the drive space.
If you breaking your VM into 2GB chunks, you will need to do it from the command line.
The command line to do it is this:
vmware-vdiskmanager
The full syntax is this (assuming you want to increase it to 10GB and your disk filename is myDisk.vmdk located in F:/VMs/MyVm/):
vmware-vdiskmanager -x 10GB "F:/VMs/MyVM/myDisk.vmdk"
You will need to run the command from VMWare directory - in VMWare Server 2.0, the directory is located at "C:\Program Files\VMware\VMware Server". So open a command prompt, navigate to the VMWare dir and execute the command above.
The command will run for a while and after it is done, it will give you a message indicating whether the expansion is successful or not.
Now once the diskspace is increased, you will need to expand the file system to its max capacity. Running the command above or through the VMWare interface only increase the max capacity of the disk, but the size of the allocated size used by the VM is still at the old size. There are several ways to do this:
1. Mount your VMDK file to you host machine using vmware-vdiskmount and then expand it using DISKPART from your host OS (vmware-vdiskmount is only available for VMWare Infrastructure & Workstation). I think you can download it from here but I have never tried to use it with VMWare Server - so try at your own risk.
2. Mount your VMDK to another VM (it has to be the same harddrive controller - SCSI/IDE) and then expand it using DISKPART from your second VM. To mount the VMDK into your second VM, follow these steps: a) Make sure both VMs are shut down b) Highlight/Focus on your second VM and click "Add Hardware" under "Commands" box, select "Hard Disk", then select "Use an Existing Virtual Disk". Browse to your first VM VMDK file and make sure the type is the same as your expanded VM under "Virtual Device Node". c) After completing the wizard, you should see the mounted drive under Hard Disk within your hardware list. d) Start your second VM e) Run DISKPART.
3. You can also use 3rd party tools such as Partition Magic or other similar tools.
Related Posts:
VMWare Server Experience
Win XP 64 bit and VMWare Server
-- read more and comment ...
By
Johannes Setiabudi
@
5:40 PM
0
comments! add yours!
Wednesday, January 14, 2009
XP 64 and VMWare Server
With Windows XP 64 bit Edition, I wanted to install VMWare Server 2.0 - the installation failed. It will do all the installation preparation and then close itself without installing anything.
Googling it around using keywords like "XP64 VMWare Server" did not yield any meaningful results (at least not in the first 4 pages or so). I almost thought that XP 64 is not compatible with VMWare Server 2.0 - but the readme says it should be OK.
After asking around, my boss at work told me that there is patch/hotfix from Microsoft that I need to install to get this working. The patch is about multiple processors and virtualization that requires processor management.
There is a KB article about this: KB896256 and you can download the patch from there.
If you are running AMD processors, you also want to apply this hotfix & drivers from AMD.
And here is the rest of it.
-- read more and comment ...
By
Johannes Setiabudi
@
4:16 PM
2
comments! add yours!
Monday, December 29, 2008
VM Ware Server 2.0 Experience
I have been doing a lot of virtualization in the past 2 months or so. The engine of choice so far is VM Ware. Microsoft also has a virtualization engine called Virtual PC - I have never used it, but a lot of people that I know use VM Ware, so basically I just follow suit. Maybe when I have a chance to play around with Virtual PC, I will write a blog post comparing them against each other.
What I want to highlight in this post is some of the tips and tricks that got mine to work as I needed. Your needs may differ, but hopefully some of these are generic enough that they can still be helpful.
VM Ware Server site: http://www.vmware.com/products/server/
When you click download, you will need to fill in a form to get your key. It is free, so go ahead and fill in the form and the instruction to get the key will be emailed to you. Once you get the downloaded file, run it to execute the installation procedure.
Installation is pretty straight forward - just follow the instruction provided by the installer. At some point, you will be required to enter a license key - this is the key you got from the registration process.
Once the installation is done, usually it will create a shortcut on your desktop called "VMWare Server Home Page". This is the main executable that will launch the interface for VMWare Infrastructure interface. When you run it (by double clicking it), it will open a browser (whatever browser set to be the default) and there are 3 things that you will typically see.
1. There is a problem with this website's security certificate. If you get this screen/page, all you need to do is to click on the second link on the page that says "Continue to this website (not recommended). "
Then on the next screen you will get a login screen. This is a login to the VMWare Infrastructure interface - you can login using the username and password that you use to login to the computer. So if you login to the computer using "myname" and with password "mypassword", then you use the same username & password to login to this VMWare web interface.
If your machine is in the domain, you do not need to include your domain name in the login process. So instead of login with DOMAIN\username, just use "username".
2. Internet Explorer cannot display the webpage. If you get this screen when you open the VMWare Server Home Page, I will check several things: a) Is the URL correct? b) Is the port number correct? c) Is VMWare Host Agent service running? You can check this in "Services", located in Administrator Tools under Control Panel. If this service does not exist, you will need to reinstall VMWare Server. If it is there and not running, you need to start it. Once it is started, close all browser with VMWare stuff in it, and try again.
Also keep in mind, in FireFox or other browsers, it may look different.
3. VM Ware also has this tool that's called VM Ware Converter 3.0. This is a very useful tool to convert your physical PC into a VM or vice versa. It also allows you tp change the configuration of your VM by cloning it. The free version has limited functionality, but it should be able to do the things I mentioned above. The paid version has more robust functionality.
Related Posts:
How to Increase HD Space in a VM
Win XP 64 bit and VMWare Server
-- read more and comment ...
By
Johannes Setiabudi
@
9:19 AM
3
comments! add yours!
Tuesday, December 16, 2008
CSLA & ASP.NET MVC (part 3: Adding)
As I have mentioned previously in the last post, editing and adding is not that much different - one pulls an existing one and modify it with incoming data, the other is just creating a new instance and filling it up with incoming data. We discussed "editing" in my last post, and now we are going elaborate on "adding".
First, let's take a look on the displaying of the empty form. This one is pretty easy, just get a new customer and bind it into the model as CurrentCustomer.
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult New()
{
viewData.CurrentCustomer = Customer.NewCustomer();
viewData.CustomerList = CustomerInfoList.GetCustomerInfoList();
viewData.Titles = TitleInfoList.GetTitleInfoList();
return View("New", viewData);
}
We also want to bind the list of titles to be able to populate the drop down for title selection.
in handling the post, we are doing essentially the same thing as in edit, except this time we are mapping it to en empty object since it is a new one. [ActionName("New"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create()
{
try
{
Customer customer = Customer.NewCustomer();
UpdateModel(customer, new[]
{
"TitleId",
"FirstName",
"MiddleName",
"LastName",
"DOB"
});
customer.DateEntered = DateTime.Now;
customer.DateUpdated = DateTime.Now;
if (!customer.IsValid)
{
foreach (Csla.Validation.BrokenRule brokenRule in customer.BrokenRulesCollection)
{
ModelState.SetAttemptedValue(brokenRule.Property, brokenRule.Property);
ModelState.AddModelError(brokenRule.Property, brokenRule.Description);
}
viewData.Titles = TitleInfoList.GetTitleInfoList();
viewData.CurrentCustomer = customer;
return View(viewData);
}
else {
customer.Save();
TempData["Message"] = "I saved " + customer.LastName + " to the database";
return RedirectToAction("List", "Customer");
}
catch (Exception ex)
{
TempData["ErrorMessage"] = ex.Message;
return RedirectToAction("New");
}
}
So upon save, we want to display the confirmation message whether there is an error or the record is saved successfully. In the code above we also utilize CSLA rules validation - this is really useful in a way that we have a central place to put our format rules, business rules, validation at. If there is an error, we want to redisplay the new customer screen and if save is successful, we want to update the list with the current data.
Related Posts:
ASP.NET MVC, AJAX, jQuery
CSLA & ASP.NET MVC (part 1)
CSLA & ASP.NET MVC (part 2)
-- read more and comment ...
By
Johannes Setiabudi
@
4:36 PM
0
comments! add yours!
Saturday, December 13, 2008
CSLA & ASP.NET MVC (part 2: Editing)
In the last post, we discussed about listing viewing detail for objects built with CSLA framework via ASP.NET MVC. Now in this post, I will show the editing and adding of the object - in our example here, using "Customer".
In essence, editing and adding is not that much different - one pulls an existing one and modify it with incoming data, the other is just creating a new instance and filling it up with incoming data. In our code, we try to leverage CSLA as much as possible, where the "Save" method is called only when the object is "dirty". Another thing is that we also want to get as much as data validation within the CSLA object as possible rather than manual/custom checking in our controller.
First, editing. [AcceptVerbs(HttpVerbs.Get)]
public ActionResult Edit(int id)
{
viewData.CurrentCustomer = Customer.GetCustomer(id);
viewData.Titles = TitleInfoList.GetTitleInfoList();
return View("~/Views/Customer/Controls/CustomerEdit.ascx", viewData);
}
The method Edit is tagged with "AcceptVerbs" attribute and scoped to only accept "Get" request. What this means is that this method can and will only be executed during a GET. Scott Guthrie has an excellent post regarding this attributes in his blog - I suggest for you to check it out.
The rest of the code is pretty simple, get the Customer record that is selected (passed in as a Id parameter in the method), put the customer instance into my viewData, get the list of titles to populate my Titles drop down, and then pass the view data into the viewer - pretty straight forward.
Now, let's take a look at the handler code for edit submission/post - for when somebody hit submit on our edit form. [ActionName("Edit"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update(int id)
{
try
{
Customer customer = Customer.GetCustomer(id);
UpdateModel(customer, Request.Form.AllKeys);
if (!customer.IsValid)
{
foreach (Csla.Validation.BrokenRule brokenRule in customer.BrokenRulesCollection)
{
ModelState.SetAttemptedValue(brokenRule.Property, customer.GetType().GetProperty(brokenRule.Property).GetValue(customer, null).ToString());
ModelState.AddModelError(brokenRule.Property, brokenRule.Description);
}
viewData.CustomerList = CustomerInfoList.GetCustomerInfoList();
viewData.Titles = TitleInfoList.GetTitleInfoList();
viewData.CurrentCustomer = customer;
viewData.ValidationErrorFlag = true;
return View("~/Views/Customer/Controls/CustomerEdit.ascx",viewData);
}
else
{
if (customer.IsDirty)
{
customer.DateUpdated = DateTime.Now;
customer.Save();
TempData["Message"] = "I saved " + customer.LastName + " to the database";
}
else
{
TempData["Message"] = "There were no changes to be made";
}
return null;
}
}
catch (Exception ex)
{
TempData["ErrorMessage"] = ex.Message;
return RedirectToAction("Edit", new { id = id });
}
}
OK, that seems long - so let's examine the code bit by bit so we can fully understand what is going on. If you notice, above the method name, there is also an "AcceptVerb" attribute, but this time it is set to "POST". Another thing is that it has ActionName("Edit") - which when combined with the AcceptVerb attribute, it will have the meaning that if there is an action "Edit" called on the controller with a POST, it will then get redirected into this method "Update".
try
{
Customer customer = Customer.GetCustomer(id);
UpdateModel(customer, Request.Form.AllKeys);
...
The 2 lines of code above, it is basically getting the Customer record being edited, and then call "UpdateModel" method, where it tries to match the instance of Customer called "customer" with the data submitted into the Request.Form. if (!customer.IsValid)
{
foreach (Csla.Validation.BrokenRule brokenRule in customer.BrokenRulesCollection)
{
ModelState.SetAttemptedValue(brokenRule.Property, customer.GetType().GetProperty(brokenRule.Property).GetValue(customer, null).ToString());
ModelState.AddModelError(brokenRule.Property, brokenRule.Description);
}
viewData.Titles = TitleInfoList.GetTitleInfoList();
viewData.CurrentCustomer = customer;
viewData.ValidationErrorFlag = true;
return View("~/Views/Customer/Controls/CustomerEdit.ascx",viewData);
}
...
Here we check whether the instance filled with data from the form is valid based on the rules specified in the CSLA rules. If it is not valid then iterate the broken rules collection and set the model marked with error messages appropriately. Now after the model is marked with the error, we want to display back the form with the model so the error messages can be displayed accordingly field by field. To do this, we then populate the Titles field in our viewdata back with list of available titles, and also populating our CurrentCustomer property with the edited customer, set the error flag and return the viewer for "Edit". else
{
if (customer.IsDirty)
{
customer.DateUpdated = DateTime.Now;
customer.Save();
TempData["Message"] = "I saved " + customer.LastName + " to the database";
}
else
{
TempData["Message"] = "There were no changes to be made";
}
return null;
}
...
If the instance does not violate any rules, then we can save if necessary. Even though CSLA will detect automatically whether the instance is dirty or not before saving to the database, but we chose to check in our controller so we then can display whether there are data being saved or not. Since there is nothing else needed to be done after the saving, we then return null value.
Related Posts:
ASP.NET MVC, AJAX, jQuery
CSLA & ASP.NET MVC (part 1)
CSLA & ASP.NET MVC (part 3)
-- read more and comment ...
By
Johannes Setiabudi
@
10:22 PM
0
comments! add yours!
Thursday, December 11, 2008
Jonathan is 3 years old - time flies!
Three years ago, early December was nervous time for me. Helen, my wife, was pregnant and the baby is due anytime. Jonathan was born Dec 10th 2005, 7am, @ Riverside hospital - 51cm, 7lbs 8oz. There were no complications, the delivery was smooth, and we went home being proud parents.
The first couple of months were rough. Helen sister stayed with us for the rest of the year and went home end of December. My mom came after that and stayed for 2 months to help us along. Jonathan loves his milk and he had no problem with food or milk. He had eczema on his cheeks which worried us for a bit, but after the 1st year and a half it pretty much went away. He started eating solid food at 4 months, and by that time, Jon could hold his own bottle. He was huge fir his age at the time - I believed he was in the 70-90 percentile back then.
Another thing we worried about back then was that Jon threw up a lot, especially when he was crying. This led us to eventually not allowing him to sleep by himself in the crib until he was almost 2 years old. Putting a humidifier in his room helps a lot too.
Jon started walking on his own when he was 11 months. I remembered that his first attempt to walk across the room in our living room was during a OSU-Michigan game (OSU won 42-39 - GO BUCKS!!). He was a fast walker and he was the type that cannot stay still - so we installed gates in our house to prevent him from going too far or going into unsafe rooms. Grandma and grandpa came during Jon's 1st birthday and we threw a party. Since the Buckeyes were going to National Championship that year, the theme for the party was "Buckeyes". Everybody came wearing scarlet or grey apparels. Even though Jon has not understand football yet at the time, but he was able to respond to "O-H" with an "I-O"! I was soo proud ...
Jon 1st birthday party!
Jon and his first snow ...
Jon's first haircut - done by mommy and daddy!
Halloween!
By the time Jon was 2 years old, he was talking Indonesian and English, sleeping on his own bed, ate all kinds of food, understand that OSU is the best, what an email is, how to chat to daddy, etc etc.
Jon's 2nd birthday party - can't wait to eat cake!
Yesterday was Jon's 3rd birthday - o how time flies. He is wearing bigger clothes now, brushes hi own teeth, talks in full sentences, ask the most difficult question I can ever imagined ("Why daddy has to go to work?"), loves staying in a cabin, etc. Jon loves his train set (me too) and looking forward to have it expanded. Taking pictures of Jon regularly also pays off big time.
BTW, Jon now has his own blog, written by mommy - http://jonathansetiabudi.blogspot.com, check it out.
-- read more and comment ...
By
Johannes Setiabudi
@
9:36 PM
0
comments! add yours!
Wednesday, December 10, 2008
CSLA & ASP.NET MVC (part 1: listing & viewing detail)
The easiest implementation for ASP.NET MVC is usually via LINQ to SQL. Now, for larger projects that must be scalable, one will need object development framework that is also scalable and more robust. My framework of choice CSLA.NET. Assuming you have built your CSLA classes, wiring it in with MVC is a piece of cake.
I recommend to make your view to be strongly typed to the object of your controller. So in my example, I have a CSLA class for "Customer" and also its corresponding read-only list, read-only item, editable, etc. Hence, I name my controller to be "CustomerController". In it, I created a class to carry around stuff as a single object, instead of stuffing everything in ViewData and cast when needed. public class CustomerControllerViewData
{
// list of read-only customer available to me
public CustomerInfoList CustomerList { get; set; }
// current editable customer seleted
public Customer CurrentCustomer { get; set; }
// list read-only Title available to the Customer
public TitleInfoList Titles { get; set;}
}
Then in the controller class, I declared a global variable to hold the instance of the CustomerControllerViewData class. I initialized it right away. public class CustomerController : Controller
{
CustomerControllerViewData viewData = new CustomerControllerViewData();
public ActionResult Index()
{
return RedirectToAction("FullList");
}
...
}
During list, I put all the necessary data into CustomerControllerViewData class, rest the validation, and then I pass that instance into the viewer as a strongly typed model. I do not fill in the CurrentCustomer property nor the Titles - since I won't be needing those to display my list of customers. public ActionResult List()
{
viewData.CustomerList = CustomerInfoList.GetCustomerInfoList();
viewData.ValidationErrorFlag = false;
return View("~/Views/Customer/Controls/CustomerListing.ascx", viewData);
}
The viewer looks like this - it should be pretty simple with the exception that it is strongly typed. So in the code behind, I have to add the type in the generic constructor of the viewer: public partial class CustomerListing : System.Web.Mvc.ViewUserControl
{
...
}
Now for viewing detail if a customer, we also do not need to fill out CustomerList property, since at this point we only care about a specific customer. Titles is needed since to populate a look up/drop down field. public ActionResult Detail(int id)
{
viewData.CurrentCustomer = Customer.GetCustomer(id);
viewData.Titles = TitleInfoList.GetTitleInfoList();
viewData.ValidationErrorFlag = false;
return View("~/Views/Customer/Controls/CustomerDetail.ascx", viewData);
}
Do the same thing for the code behind of the viewer to make it strongly typed: public partial class CustomerDetail : System.Web.Mvc.ViewUserControl
{
...
}
Related Posts:
ASP.NET MVC, AJAX, jQuery
CSLA & ASP.NET MVC (part 2)
CSLA & ASP.NET MVC (part 3)
-- read more and comment ...
By
Johannes Setiabudi
@
10:18 PM
4
comments! add yours!