Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Friday, January 30, 2015

Explicit operator

According to MSDN, explicit operator keyword declares a user-defined type conversion operator that must be invoked with a cast. This is super handy if you are doing a lot of conversion/translation in your code.

Here is an converting between two separate classes, Person and Contact - which have translatable properties between them.

public class Contact {       
        public string Name { get; set; }
        public string PrimaryPhone { get; set; }
        public string PrimaryEmail { get; set; }
}

public class Person{
        public int PersonId { get; set; }        
        public string FirstName { get; set; } 
        public string LastName { get; set; }
        public string HomePhone { get; set; }
        public string HomeEmail { get; set; }
        public string WorkPhone { get; set; }
        public string WorkEmail { get; set; }
        public string CellPhone { get; set; }
}
Then, you can create an explicit conversion operator such as this:
public static explicit operator Contact (Person person)
{
    return new Contact 
    {
          Name = person.FirstName + " " + person.LastName,
          PrimaryPhone = (String.IsNullOrEmpty(person.CellPhone) ? 
                  (String.IsNullOrEmpty(person.WorkPhone) ? 
                  person.HomePhone : person.WorkPhone) : person.CellPhone),
          PrimaryEmail = (String.IsNullOrEmpty(person.WorkEmail) ? person.HomeEmail : person.WorkEmail)
    };
}
Here is how you would use it:
Contact contact = (Contact)person;
-- read more and comment ...

Tuesday, January 20, 2015

Enabling IIS Express to Accept External Request

I am doing a web development project where the web application needs to look good on all browsers (on Mac and PC - Win7 and Win8) and mobile devices (iPad, Windows Phone, Android, etc). So most of my testing can be done in my development machine - either by running an emulator from Visual Studio, or letting the browser (i.e. Safari) emulate iPad/iPhone resolution. This probably solved 95% of the issues and problems. But, then I still want to do a real device test - where I actually run the web application and browse to it from an iPad, or a Mac, from an Android phone, etc.

Of course - the ideal solution is just to put the web application somewhere on the internet (i.e. http://mytestwebsite.mydomain.com) and let the testing begin. But unfortunately, I do not have the luxury of a QA or test site. So I just have to run it locally.

I can set it up on my IIS, but that seems to be a hassle - removing/stopping my current site running in IIS, setting up this new site, creating all the permissions, app pool, etc. Too much overhead for simple testing. Can I just hit F5, or run the IIS Express and make it accepting external request - so I can hit the site from outside of my dev machine? YES!

Allowing everyone to access http://mydevmachine:80

Open up an admin elevated command prompt and type in this command:
      netsh http add urlacl url=http://mydevmachine:80/ user=everyone

Open up firewall

Now, we need to open up the Windows Firewall for allow traffic to go through. In the same command prompt from above, type in this command:
      netsh firewall add portopening TCP 80 IISExpressWeb enable ALL

Configure IIS Express

Lastly, we need to add our machine name into the IIS Express configuration. You can find the config file located in C:\Users\\Documents\IISExpress\config. Open the file using any text editor and find the web application configuration. My web application is named "Domain.Site.Mvc" in this example.
<site name="Domain.Site.Mvc" id="4">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
        <virtualDirectory path="/" physicalPath="c:\Projects\Domain.Site\Domain.Site.Mvc" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:12555:localhost" />
        <binding protocol="http" bindingInformation="*:80:mydevmachine" />
    </bindings>
</site>

Now, I can start my site on my dev machine and then browse to it from separate machines, Mac machine, phone, tablets, etc by just going to http://mydevmachine/. With the exception of an iPad. For whatever reason, iPad does not allow browsing to a local machine name - it has to be a fully qualified domain name. I will write a solution to this on a separate blog post.
-- read more and comment ...

Tuesday, September 3, 2013

How to expose internal methods to a different assembly

Let's say you create this method - let's call it MethodX. Now MethodX is only used within the project - so you marked it as "internal". So now you want to test this MethodX.

Now, I know that in theory MethodX is used internally in the project, which exposing public members of public classes etc - and those public classes and their members are the ones ought to be tested. Using MethodX or not is an implementation detail that the consumer does not need to know, hence does not need to be tested specifically. Yupe, agreed - that is all good.

Now, let's set that aside for a moment - and if you want to test the internal MethodX directly, how would you do it? Of course, the easiest solution is by making MethodX (and the class containing it) to be public. But, then you must remember to convert it back (and forth) every time you run your tests - which is quickly becoming a pain.

It turns out, there is a flag/attribute that you can set in your class declaration to specifically mark a class and its internals to be visible to a different set of assembly. Take a look at this example below:
[assembly:InternalsVisibleTo("MyProject.Tests")]
namespace MyProject
{
    public class MyClass 
    {
        internal void MethodX() 
        {
            // ...
        }
    }
} 
So normally, although the class MyClass is public and is available to public, but the method MethodX is not accessible from outside the same assembly. But, upon putting the InternalsVisibleToAttribute, now MethodX is accessible from MyProject.Tests assembly. If this consuming assembly is your test project, then you can start to build a test for it just like testing against a public method.
-- read more and comment ...

Sunday, April 7, 2013

Properly Deleting Database for Database-Migration

I am working on a simple brand new project with ASP.NET MVC and decided to try EF to connect to my database. This gives me the opportunity to learn EF Code-First, database-migration, etc.

Everything seems to be pretty intuitive until when I am running "update-database" from the Package Manager Console. I created my Configuration class, turn-on automatic migration, and populated my database using Seed method, made sure all my context are correct.

[TL;DR]

When one need to delete/recreate a database, do not delete the mdf file from App_Data, but instead go to "SQL Server Object Explorer" and find your database under (localdb) and delete it from there.

FULL VERSION:


Then, since I want to recreate my database, I delete my database (mdf file) from my App_Data folder under Solution Explorer and then run "update-database". See picture on the left.

But then I am getting an error:
Cannot attach the file D:\Projects\MvcApplication1\App_Data\aspnet-MvcApplication1-20130407085115.mdf' as database 'MvcApplication1'.
I looked in the file explorer and the mdf file is surely gone. Try to close Visual Studio and reopen, same error.

Well, the database was initially created when I try to "Register" or create an account using the site (it's using SimpleMembershipProvider) - so maybe it will recreate it if I simply run the site and try to register again. But then I am getting the same error when running the website.

I went to the recycle bin, restore the mdf file and ran the project again - it worked. It did not have the new tables or new data, but no "cannot attach" error. Restoring this file also restore my default connection. If I try to delete the mdf file again, then my project won't run and my database-migration also won't run.

I almost resort to think that "Code-First" is a lie - that I simply have to add the new tables manually in the SQL table designer, etc. This is so confusing - should not be that hard, I think.

So with the mdf file deleted, I went to Server Explorer and checked that my connection to the database is gone - there is nothing under "Data Connections".

So maybe I need to delete the data connection instead of deleting the mdf file from App_Data? So I did a restore again from my Recycle Bin, made sure my project ran, and then I deleted my connection from the Server Explorer, rebuilt the project and ran it. It worked! But my delight is short-lived, since then I realized that deleting the connection does not necessarily mean deleting the database - which I quickly checked that my mdf file still in the App_Data folder. I simply deleted the connection to view the database via Visual Studio.

I tried more and more things - which increase the frustration level - because at this point I am stuck in my project and all I have been trying to do is to modify my database schema. If I did this using the old way using SQL Management Studio or SQL Express, or even Linq-to-SQL, I could have been making a huge progress in my project.

SOLUTION

Until I stumbled on "SQL Server Object Explorer" under "VIEW" in your VS Studio 2012 top menu/toolbar. I noticed that although my mdf file is deleted from my App_Data folder, but under "SQL Server Object Explorer", my database is still registered under (localdb)\v11.0\Databases.

Out of curiosity, I deleted my database from there and re-ran my project - it worked. It recreated my database (without the new tables and seed data). So I deleted it again from SQL Object Explorer, and ran "update-database" - it ran successfully this time. EUREKA!!

So lesson learned: when one need to delete/recreate a database, do not delete the mdf file from App_Data, but instead go to "SQL Server Object Explorer" and find your database under (localdb) and delete it from there.

-- read more and comment ...

Sunday, June 19, 2011

Using Dapper.NET to Boost DAL Performance

Lately, my focus has been to optimize and increase the performance of our web-application. This, of course, includes load time and speed - among other things. There are a lot of performance enhancements that we can do to speed up our load time, from the UI stack (javascript loading, CDN, minimization, etc), DB stack (indexing, query caching, stored procs, etc), application/biz layer stack (algorithm optimizations, data storage, caching, etc).

Now, our web-app is using Linq-to-SQL as our DAL and since a year ago, we have been doing several things to speed up our DAL - by using compiled queries, creating stored procs, views, etc. One of the tools or library that I have been using to boost DAL performance is Dapper.NET.

-- read more and comment ...

Sunday, April 10, 2011

Utilizing pass-by-ref Parameters

I recently helped a friend of mine code an application and at some point I created a method using a pass-by-reference parameter. Apparently this is new to him. I asked several other programmer friends that I know and most of them either know about it but never use it or don't know about it. So - here is a post about it.

To illustrate the usage of pass-by-reference, I will create to a simplistic example - where we want to calculate a loan amortization: with initial loan, interest rate, and loan period - and resulting in: monthly payment and total interest over loan term

So in code, without the pass-by-reference, we have to do this somewhat in 2 steps/methods:

    decimal monthlyPayment = CalculateMonthlyPayment(initialLoan, rate, period);
    decimal totalInterest = CalculateTotalInterest(initialLoan, rate, period);
With the definitions:
public decimal CalculateMonthlyPayment(decimal initialLoan, double rate, int period) { 
        decimal result;
        // calculate monthly payment
        return result;
    }

    public decimal CalculateTotalInterest(decimal initialLoan, double rate, int period) { 
        decimal result;
        // calculate interest
        return result;
    }


-- read more and comment ...

Wednesday, March 2, 2011

Integrating ELMAH into your ASP.NET MVC project

What is ELMAH? ELMAH stands for Error Logging Modules and Handlers. So it does what it says, logging errors. It's a plug-able stand alone module that you can integrate with your project quite easily.

From ELMAH's site:
Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilities without changing a single line of your code:

  • Logging of nearly all unhandled exceptions.
  • A web page to remotely view the entire log of recoded exceptions.
  • A web page to remotely view the full details of any one logged exception.
  • In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
  • An e-mail notification of each error at the time it occurs.
  • An RSS feed of the last 15 errors from the log. 
Sounds awesome! Hell yes - beats writing your own any day! How do you integrate it with ASP.NET MVC project?

1. Download ELMAH
You can get the compiled assemblies or the source files here: http://code.google.com/p/elmah/

2. Reference ELMAH's assemblies
If you get the compiled assemblies, just make a reference to Elmah.dll. If you get the source, you will need to build it and then reference it (either by project or by binary).

3. Modify web.config
Open your web.config and make these changes:
a. Add this "configSections" within "configuration"
<configSections>
        <sectionGroup name="elmah">
            <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
            <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah"/>
            <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah"/>
            <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/>
        </sectionGroup>
    </configSections>
b. Add this "elmah" section within "configuration" under the "configSections". This will enable ELMAH to save the error log to the database using "MyAppConnectionString" connection string. If you want to save the log into XML files on a local disk, you can uncomment the second line (and comment the 4th line) and specify the saving location under "logPath".
<elmah>
        <!--<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/App_Data"/>-->
        <security allowRemoteAccess="1"/>
        <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="MyAppConnectionString"/>
    </elmah>
c. Within "system.web" section, add these lines:
<httpHandlers>
            <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>
        </httpHandlers>
        <httpModules>
            <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
        </httpModules>
d. Within "configuration", configure the permission to see the log. Basically it will deny all users unless users are logged in and user name is listed in the "allow" list. Enable that by adding these lines:
<location path="elmah.axd">
        <system.web>
            <authorization>
                <allow users="admin,joe,bob"/>
                <deny users="*"/>
            </authorization>
        </system.web>
    </location>

4. Modify global.asax
Check in your global.asax whether this line exists:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
If it is, then no more changes are needed in the global.asax.

5. Preparing Database
If you elect to store the log in the database, then some tables and stored procedures must be created before ELMAH can be functional. Get the script to create all those tables & stored procedures here: http://code.google.com/p/elmah/wiki/Downloads?tm=2 and run it.

That should be it and ELMAH is ready to run - you can start accessing ELMAH under /elmah.axd from your root url.

But I went a step further - I want all exception, including handled one to also be captured in ELMAH. ASP.NET MVC provides an filter-attribute called "HandleError" to handle/catch all errors/exceptions happening in the controller or bubble all the way to the controller. So instead of using that, I made my own HandleError attribute that will log to ELMAH - and replace the stock [HandleError] with my [ELMAHHandleError] attribute.

6. Create [ELMAHHandleError] for all my controllers.
I took this code from NerdDinner example that ASP.NET team provides in CodePlex.
public class ELMAHHandleErrorAttribute : HandleErrorAttribute {
        public override void OnException(ExceptionContext context) {
            base.OnException(context);

            var e = context.Exception;
            if (!context.ExceptionHandled   // if unhandled, will be logged anyhow
                    || RaiseErrorSignal(e)      // prefer signaling, if possible
                    || IsFiltered(context))     // filtered?
                return;

            LogException(e);
        }

        private static bool RaiseErrorSignal(Exception e) {
            var context = HttpContext.Current;
            if (context == null)
                return false;
            var signal = ErrorSignal.FromContext(context);
            if (signal == null)
                return false;
            signal.Raise(e, context);
            return true;
        }

        private static bool IsFiltered(ExceptionContext context) {
            var config = context.HttpContext.GetSection("elmah/errorFilter") as ErrorFilterConfiguration;

            if (config == null) return false;

            var testContext = new ErrorFilterModule.AssertionHelperContext(context.Exception, HttpContext.Current);

            return config.Assertion.Test(testContext);
        }

        private static void LogException(Exception e) {
            var context = HttpContext.Current;
            ErrorLog.GetDefault(context).Log(new Error(e, context));
        }
    }

That's it!

For further reading:

-- read more and comment ...

Tuesday, February 8, 2011

Performance Tips (LINQ to SQL)

One part of the application that I am working on is performing poorly. According to the performance measurement that I get from using EQATEC profiler, it takes 3-4 seconds to load this page.

IIS / UI 
Since this is a web application, so I made sure all the IIS/non-application performance enhancements are in place:

  • IIS compression are turned on
  • Javascript files are combined and compressed
  • CSS files are combined and compressed
  • Images, scripts, and CSS files are cached
  • Conforming to YUI rules & Google PageSpeed performance rules
Setting all those boost some performance in my application - not really that noticeable in normal usage. It cut down about 0.5 seconds or about 13% or my load time. So now we are in 2.8-3.5 seconds range. So what else?

-- read more and comment ...

Monday, January 31, 2011

Using Except() Method in LINQ

There is a method that I rarely use in LINQ called "Except" - but it comes handy in my latest coding. So I thought I'd share how I use it. This method is for an IEnumerable and has multiple signatures: one that takes a second IEnumerable to exclude and the other one takes an IEnumerable and a comparer. You can read the spec in full here.

Here is an example:

int[] oneToTen = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] oneToTenEven = { 2, 4, 6, 8, 10 };
int[] oneToTenOdd;

// do some exclusion here
oneToTenOdd = oneToTen.Except(oneToTenEven);

// so that oneToTenOdd will have { 1, 3, 5, 7, 9 };
OK - that looks simple. But what about when the IEnumerable is of type T or some other complex type? This is where the second signature comes in handy. In this scenario, we will have to make our own comparer class to specify how we want both list items to be compared against each other.

Imagine this hypothetical situation where you are at a dealership and want to separate the cars that have been washed and ones that have not. Cars may have the same make, model, color, type, but each has different VIN number.

IEnumerable<Car> allCars = GetAllCars();
IEnumerable<Car> carAlreadyWashed = GetCarAlreadyWashed();
IEnumerable<Car> carNotWashed;

// do some exclusion here
carNotWashed = allCars.Except(carAlreadyWashed);

The above code which will normally work for simple comparison, won't work because the run-time will have no idea that it has to compare based on VIN number. We have to tell it to use that field to do comparison.

public class CarComparer : IEqualityComparer<Car> {
    public bool Equals(Car x, Car y) {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

         //Check whether the Car' properties are equal.
        return x.VIN == y.VIN;
    }

    // If Equals() returns true for a pair of objects
    // then GetHashCode() must return the same value for these objects.
    public int GetHashCode(Car car) {
        //Check whether the object is null
        if (Object.ReferenceEquals(plan, null)) return 0;
        //Get hash code for the VIN field.
        int hashCarVIN = car.VIN.GetHashCode();
        return hashCarVIN;
    }
}
Now then we can modify our code to be such as this:

IEnumerable<Car> allCars = GetAllCars();
IEnumerable<Car> carAlreadyWashed = GetCarAlreadyWashed();
IEnumerable<Car> carNotWashed;

// do some exclusion here
carNotWashed = allCars.Except(carAlreadyWashed, new CarComparer());


-- read more and comment ...

Friday, January 7, 2011

Microsoft Certification exams

My employer (AWH - http://www.awh.net) encourages us (the employees) to take MS certifications. Not only this will benefit the company in maintaining our status as a Gold Partner, but also will benefit us as far as knowledge, new technology, etc. Plus the certifications are attached to the individual, so if you change jobs, those certifications certainly belong in your resume and can be leveraging points.

AWH will pay for the tests, including first failure. So if I take a test and fail, and then retake the test and pass, AWH will cover both exams. So I have to pass before the reimbursement can come through.

Anyway, so last November, I saw a promotion on Prometric's website for a 2/3/4/5 exam packets with discounted price and FREE retakes for each exams in the packet. With that good deal in mind, I decided that I will set a goal in this area: getting a MCPD - Microsoft Certified Professional Developer. This certification requires 4 exams:

  • TS 70-515 - ASP.NET 4.0, Web Forms, MVC, IIS
  • TS 70-516 - ADO.NET, LINQ, EF
  • TS 70-513 - WCF
  • TS 70-519 - Web application solution/architect
I took the first test early in December and passed it quite easily. Since ASP.NET is what I use daily, most of the questions in the test are familiar to me and I can answer them correctly.

I scheduled to take the ADO.NET test on Dec 23rd, but when I came to the facility, it was closed. I was not notified of any closing and Prometric also was not aware of the closing of the local facility (New Horizons). Prometric was able to reschedule me for Dec 27th at a different facility. I failed my ADO.NET test - probably by 2 or 3 questions, it was so close. Although I use ADO.NET stuff pretty much daily, but there are some things in there that are pretty new to me and I have not used them in production quality code - like Entity Framework. Those questions stumped me and resulting in a failing grade. Thank God for the free retake!

So I studied more EF, practice making some projects with with etc and retake the test on December 29th. I passed.

So next up is WCF - scheduled for Jan 12th. Hopefully by end of Feb 2011, I will have become an MCPD.

-- read more and comment ...

Thursday, October 7, 2010

Conditional Reference in VS 2010

In one of our projects, we are using some third party components that have separate dlls for 32 bit and 64 bit. Since our old development box and production server were 32 bit, so we used the 32 bit version. No problem whatsoever.

In a different project for different client, our development box is a 64 bit machine. But, since we are running VS 2010 and using Cassini for our debugging, we use the 32 bit reference. But since our production box is running 64 bit, last minute before build for release in our build server, we swap the reference to 64 bit, re-check-in and build. So we just keep doing it that way - until one day, we forgot to do that and a production build got pushed to production environment and (of course) it breaks. So we fix it and then we vowed to find a solution to the last minute reference swap thing.

So here is how we fix it:
In VS, right click on the project that has the reference to the 32/64bit ref, do an unload project and open using XML editor and in it, you will see something like this:
...
    <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    </PropertyGroup>
...

    <ItemGroup>
        <Reference Include="Project.Reference.MyProject">
            <HintPath>..\References"Project.Reference.MyProject.40.x86.dll</HintPath>
        </Reference>
    </ItemGroup>
...
What you need to do is add a condition in your project file, so on certain environment it will use the x86 and x64 for other. The easiest way to do this (which is what we did) is adding a conditional statement itself on the reference element - when compiled as "debug", use the x86 dll and to use the x64 when compiled as "release". So we changed it to be like this:
 
...
    <ItemGroup>
        <Reference Include="Project.Reference.MyProject" Condition="'$(Configuration)' == 'Debug'">
            <HintPath>..\References\"Project.Reference.MyProject.40.x86.dll</HintPath>
        </Reference>
    </ItemGroup>
    <ItemGroup>
        <Reference Include="Project.Reference.MyProject" Condition="'$(Configuration)' == 'Release'">
            <HintPath>..\References\"Project.Reference.MyProject.40.x64.dll</HintPath>
        </Reference>
    </ItemGroup>
...
-- read more and comment ...

Thursday, August 26, 2010

VS 2008 locking up after Office 2010 install

I installed MS Office 2010 about 3 weeks ago and everything went smooth. For the most part, I have been developing in VS 2010, but lately, when I was doing code review, I have to a .NET 3.5 project in VS 2008 - and it locks up on me almost every time.

I thought it was some extension I installed or something screwed up on my project. So I uninstall all extensions, but it was still locking up. I open the project on a different computer, it was running fine, same source and references and all that. I went to search on the internet and found out that there are some issues between VS 2008 and Office 2010 installation. One my particular issue, all I need to do is to rerun "Microsoft Visual Studio Web Authoring Component".

The setup.exe file is located at : C:\Program Files (x86)\Common Files\microsoft shared\OFFICE12\Office Setup Controller\.

So just shut down all VS 2008 instance and any Office programs and then run the Setup.exe and it should be good to go - at least that did it for me.

Credit to Martin Hinshelwood!
-- read more and comment ...

Monday, June 7, 2010

VS 2010 Coded UI Test

Last year, ASP.NET Test team release ASP.NET Lightweight Automation Framework and I blogged about it here. With VS 2010 Ultimate, you now can use "Coded UI Test" - which I think replaces it as a whole. The Coded UI Testing minimizes coding and recorded your actions - while also allowing coding and customization.

So how it works is basically like this:

  1. It records your behaviors (on a browser/WPF/Silverlight etc application) 
  2. Then it tries to guess what you are doing (moving a mouse, hover, waiting, clicking a button, typing text, etc).
  3. Generate code to replicate your behaviors/actions based on its guess. 
  4. You can also create assertions, to check whether certain elements (like texbox) has certain value, some labels display certain text, etc.

I have to say that for my web application that I am working on, it does an excellent job. It does all the low end work of recording my actions - and all I have to do is string them all together into a coherent sequence of actions in my tests.

MSDN has an excellent walk through on how to start one and customizing it to fit your needs and I am not going to repeat it in my post. You can read the MSDN how-to here.

In my experience in using it, it has its quirks:
  1. In some AJAX scenarios it will retain the old value or view of certain actions. So let's say you are looking at a product administration "Detail" screen and you click "Edit" to bring up the editing capability. Upon save, your application then brings you back to the "Detail" screen. In this scenario, sometimes upon "Save", the Coded UI test still holds the old "view" of the "Detail" screen instead of reloading/refreshing with the new "Detail" screen with the new/updated values. As a result, when you have an assertion to check whether certain values are updated, it will fail.
  2. Updating and deleting an assertion test or a recording is quite difficult. You have to manually delete it in code all the way. Updating certain test is also quite difficult if you want to do it manually. So for example if I have a test that checks whether a particular textbox value is "Something" and I want to change it to check for "some things" instead, intuitively I went to look for the line of generated code and change the checking value. But upon running, the code is regenerated and my changes are reverted back to "Something".
  3. The generated code also combine most of the generated code into 1 UI map. Which gets huge once you start building multiple tests. MSDN has a walkthrough on how to build tests using multiple UI mappings, but it is quite a challenge.
Beyond those issues that I have experienced so far, the tool itself is pretty impressive and I like it.

Some more readings and how-tos from MDSN

-- read more and comment ...