Microsoft download search


I got invited the beta for download search. Nah, this is not NDA material, just the "luck" of the draw. During early beta, it happened a few times, as well.

My Impression: Is "sucks" a good enough word. Probably not very productive, so let me explain how I use the download search and why it sucks to me.

My norm is to go in and search the latest entries in downloads. To do this, on old (not so pretty) search, I click advanced then sort by date and choose 50. I then scan. On the new (pretty – Silverlight) search, I have to search for nothing first and then resort by date. So far, pretty much the same (number of clicks wise).

Then, when I find a download, I either click and download or open in a new tab. With the pretty version (new), I cannot open in a new tab, so I go forth, so let’s compare the actions of clicking rather than opening in a new tab (preferred method, so already a few "sucks" points for my user experience).

In the old site, I can click back a few times and get back to my sorted list. In the new version, I click back and then resort by date and reset to 50. Lots of clicks to get back to the list sorted via my preferences. This IS something they can improve in Silverlight, however, so I am hopeful.

Impressions:

  • Advanced search is gone. While you can click and open a resort menu, this is NOT available until you search first, wasting time.
  • Load time is PITIFUL when you first load the search UGH
  • What is it with the ultra fuzzy fonts?

On the positive

  • Details pane is pretty – assume eventually, I can actually download from here rather than going to an old style download page? If so, that would remove some of my pain.

Summary

Much of the look is eye candy. It loads a bit slow, but that would be offset if you could download from the WPF "popup". Would also be nice if it could remember how I like to search, but that is just me being "selfish".

Peace and Grace,
Greg

 

P.S. Want to escape the beta, if you have been invited? Delete your cookies.

Webkinz Saga ending … for now


I finally got a call (two calls actually) from Webkinz support. They solved my problem by resetting the code. You can do this "self help" in the customer support area, if that is your problem. It did not work for me, but may for you.
 
If you have a problem, email support@webkinz.com. It seems to get a faster response. Tell them as much information about the account as you feel comfortable with and include the secret code with the animal type. It may take a few days, but they will eventually get back. If you have a blog, blog about it, as well. The more noise, the more likely they will get to you, and solve the issue.
 
I will blog later about my suggestions to the Webkinz staff, if they are tuning in, that is.
 
Peace and Grace,
Greg

More about Windows Vista


I have maintained, for months, that Vista is basically a turd. I have some friends that disagree and will even post, from time to time, that they disagree. I am now finally considering upgrading my home Vista machine to Windows XP, as well.

The problem is Vista is just too intrusive. Despite my account being an administrator, it still wants to protect me from myself and stop me from getting to specific folders. In this case, it is the Local >> Internet Temporary Files directory. My reason for desiring to get there is to find an URL of a video embedded in a web page.

No, don’t tell me how to do it, as I really don’t care. Unless you can show me how to do the following task in less than the 3 minutes it took me to do it on Windows XP, you are wasting your time. I will even tell you how I did it on Windows XP to help you in your journey.

First, go to News Channel Five and find a video. The one in question for me starts from article http://www.newschannel5.com/global/story.asp?s=7516112. Then find the actual mms link for the video in that article (not the mandatory commercial, but the actual video of the story). Then record it on your own PC.

Here are my stats:

Vista: 35 minutes and never found the actual link as I cannot gain permissions to the temporary internet files folder (as an admin, I might add)
XP: Approximately 2 minutes to find and record

Now, I accept that I might be a bit dense about Vista, as I have not completely bitten the bug. But if you can honestly do it in less time than I have on Windows XP, then you might have a case that Vista works better on this fuction. Personally, I find it annoying that I cannot, as an admin, easily search my entire drive. Perhaps your experience is different?

I already have an idea which friend will respond to this. Wink

Oh, my Webkinz saga? They contacted me twice. Once asking me to send them a ton of information and once with a toll free number. I will try the toll free number first as it cures my daughter’s anxiety quicker. We will see how they handle things on the phone, but I am hopefull. It is the first sign of life I have seen.

Peace and Grace,
Greg

Webkinz saga continued


I got an answer back from webkinz support on my query. If you read my last post, I had to attach it to a question that did not fit my problem, as they had no entry for my problem. The answer:

Hello,

Thank you for writing to us. You were having problems with your Webkinz World account.

In order for us to properly address your issue, please go to www.webkinz.com and click on the ‘Customer Support’ link, located below the ‘Log In’ button.

Once you find your specific question, please fill out the corresponding form and send us your request.

Thank you,

Webkinz Customer Support

Okay, so you are saying I have to search for my problem, which does not exist in YOUR system? Doesn’t that sound a bit … well … impossible?

The problem is simple. I have three kids with webkinz. In the clamor to get online, child 2 gave me child 3’s tag. Now she has a Penguin webkin, but a Arabian Horse online. You have a reset feature, which is telling me it cannot reset. I have no clue what piece of information it is choking on, but it will not reset the account. I can’t move the horse to my other daughter’s account, as I cannot create an account without an animal. I guess I could assign the other animal to the other child’s account, but I cannot straighten out their information. Now, they might not care, but I do. The account in question is ebeamer. And, I just sent you the secret code in an email, if you actually answer the support email (it’s possible, I guess that you only answer things coming through the support form, which you will not answer unless someone fits in a box?).

Now that I am hopping a bit, I also find it annoying that I have to create 3 parent accounts (some day four, as I have a 3 year old, as well) to administer 3 child accounts. Perhaps a single parent can have more than one child? I am not sure why this was not in the specifications.

Now, I understand about changing account names, as that is a royal pain for developers. But, changing the child’s name. Why is that impossible in the system. What if someone typos while entering the information. Same with birthdate. Why is there no facility, or at least no obvious facility, for changing information?

My kids love the world, but I am currently sitting here awaiting an answer from you, which may not come as you are asking me to find a question that does not exist.

What am I going to have to do? Options:

  1. Keep submitting help desk tickets until I annoy you enough to help me?
  2. Take the webkin I mistakenly entered in back and get another horse? That would really mess you up, as the store will likely end up with a sticker that does not work for another customer, as the employee will likely put it back on the shelf, even if I tell the story?
  3. Buy more webkinz? I don’t think that is going to be my option until this saga is over, although I can think of a clever way to help myself through this garbage doing it that way
  4. Switch my kids?
  5. Switch toys? Yeah, like that one will go over.

Come on guys. Don’t tell me "you have to write us with the proper subject" when it does not exist. Just give me a bone here.

 

Webkinz Frustration


Have your children been bitten by the Webkinz "virus" yet? If not, here is the gist. You buy a stuffed animal and get to play with it online. It is a really neat concept and I love it overall. I have just found the dark side of this addiction however.

This morning, I had two different WebKinz to set up. One for Emily and one for Annabelle. I had the two tags in front of me and started signing up Emily. No problem until the tags got mixed up and I signed Emily up for the Arabian Horse rather than the Penguin. I then spent over an hour trying to straighten out the mess. I figured I had two options.

  1. Adjust the user information and change the account to Annabelle. Unfortunatley, you cannot change the user name after signup. Dead end.
  2. Reset the account. There is an online form to do this, but it will not accept the information I am typing in and does not inform me what might be wrong (probably for "security reasons")

Now, I do not blame WebKinz World for the tag mixup. That is 100% my fault.  What I blame them for is making it nearly impossible to contact them about problems they have not forseen. I am writing this hoping they will see it and use it constructively (as I am going to send the permalink to them). Here are my suggestions for improvement.

  1. Let the use change the information. I can undestand the pet, the username, but let me adjust the actual person behind the fake identity. Yes, I realize I am a fringe case, but I am going to have to wait two or three days until you contact me to get this straightened out. If I could simply adjust the child name on the account (and then use the change accuont name feature) I would be fine.
  2. Give me an ability to contact you about something other than your world. When I hit the contact us form, I have to choose something. What about people who fall outside of the normal cases? Do you really think you have figured out all of the ways someone can make a mistake.
  3. Let me know why I am unable to delete an account or tell me you have forwarded my problem to someone who can help me. As it stands, I entered all of the information correctly, except perhaps email address (which you never asked for), so I am not sure if your form is not working or I typoed something initially. As such, I cannot help you troubleshoot and I cannot straighten out my problem.

In our ignorance, or perhaps arrogance, we developers often box our customers in. Rather than think like customers, we think we can figure out all ways that software can go wrong. And, inevitably, we are WRONG.

In this case, I am trying to help myself rather than engage Webkinz, but they have not left me that option. I then try to contact them to have them help me and they have both a) not left me enough spaces to give them a proper diagnosis of the problem (300 characters) and b) given me an option of reporting a fringe case.

At this point, I want to delete the account ebeamer and start over. But, I am now waiting for someone to contact me back (up to 4 days from now) so I can resolve this issue. I realize this is not an emergency, but my daughter sure thinks so.

Perhaps I should blog on how to improve UIs when things go wrong. Wink

Now, here is my problem, in case the Webkinz guys come here (the rest of you can ignore this, except maybe to have a laugh).

1, Have treid to remove the account (Customer Support >> Account Issues >> Can I Reset My Account?): Fill in form with information for the ebeamer account and get

YOUR ACCOUNT VERIFICATION INFORMATION DOES NOT MATCH OUR RECORDS

I assume one of two things here. I typoed something in the many things you use to verify the account. Personally, I think you have asked too much here. To reset an account, why do you need more than username, password and the tag number. Why do you need animal name, child name and birthdate. If someone has the account information, along with the tag number (aka, secret code), why should they not be able to reset? As it stands, there are three pieces of information, completely useless to the transaction, that increase the likelihood of failure and a need to contact you.

Or, why can’t the child change information for the account (or a parent?). Why cement information that need not, from an application standpoint, be cemented. I feel tis way about animal name, personally, but can understand it more.

2. Attempt to change child name and birthdate: There is absolutely no option. As I am a fringe case, this is okay, although I am sure there are other parents with more than one child who may have this same issue. I can even log into webkinz world and there is no option to change my information in the world. I can understand, somewhat, not changing the animal’s name (not really, as it seems like a simple thing to do in a database, but it is your world), but not being able to correct name or birthdate is a strong oversight, IMO.

3. Tried to move the animal to a new account. Unfortunately, I cannot create an account if the child has never signed up, so I cannot move the animal to an account that does not exist and cannot create a new account. Admitedly, also a fringe case.

Here is the optimal solution: Delete the ebeamer account so I can recreate it with the correct animal and also create a new acount with this animal. When you contact me, I can give you the secret code and we can set up both accounts.

I do have two questions, however, that bugs me. Did you never forsee a case where a parent would have multiple children with WebKinz and accidentally mixing up tags? If not, I would assume you will see more of this in the future. Second, did you imagine a scenario when one child would sign up anothers Webkinz and the parent might have to try to get it on a new account? The second one is a realistic condition, considering children. And, the only solution a parent has is to buy a second Webkinz for their child so they can create an account ot switch the "stolen" Webkinz to, as there is no way to create an account without a code to switch a Webkiz to.

One more thing. As a parent, it is very easy for me to create a parent’s account over a single child. It is harder for me to create a parent account that monitors multiple children. This is a bit shortsided, IMO, as I am sure there are other parents of multiple children who love WebKinz. Do I really have to create multiple accounts? And, why, as a parent, can I not change my child’s information. The only option you give me is to block or Unblock Clubhouse chat. Are parents really this powerless in your world? Come on, guys, give me some ability to truly do something or get rid of the parent’s account altogether. This is insulting.

As one who works with Web UIs on a regular basis, I understand that this is more the norm than an anamoly. I often get paid well to make UIs more user friendly, both in flow and in offering solutions for situations like mine. As such, I do not blame you for the lack of tools to solve my problem. I am, however, very frustrated that there is no means of contacting you without adding a tag that means nothig to my communication.

Please note that I am most interested in solving my problem, but hope this feedback helps you improve. You have a great UI, from the child’s standpoint. You also have interesting games, a good social network, etc. There is room for improvement, however, in handling fringe cases. Please contact me back as I feel like a number at this point in time rather than a customer.

Peace and Grace,
Greg

Microsoft MVC


First post in a couple of months. I think I have a valid excuse, however. This was originally intended for a Monday publish, but things got in the way.

If you are not aware of it yet, last night (December 9, 2007), the ASP.NET Team released the latest ASP.NET Extensions, which includes the MVC Framework. You cn find it here. If you are going to play with MVC, make sure you also download the toolkit here.

One note about the MVC Framework. If you are still using IIS 6 (shame on you developers who have not upgraded to Vista yet? – yeah, me too), you will have to alter your bits to use .mvc in your path. This is simply a matter of adding .mvc to the default.aspx page. Just remember to remove this prior to production compile if you want the prettier URL mappings on IIS 7. If you are coding on Vista, remember to set this to .mvc before moving to Windows Server 2003, or you will have an ugly surprise.

In this post, I am going to cover the basics of how MVC works. I will link to sites that have more code specific intros, for those who want to dig deeper. This is a level 100 or 200 discussion.

Basics of MVC

MVC stands for Model-View-Controller. The basics of rendering are handled by the view (UI bits) and the controller (piece of software that determines which view to render). The model holds the "data" you wish to make available to the user via the view. Pretty simple, but it does require a paradigm change to stop thinking in terms of ASPX pages and using ASPX merely to render.

So, why should you make the leap? Well, today there is absolutely no reason. And, if the IIS 6 bits are not changed (or IIS 7 made available for your OS), you might not want to in the future. (Yeah, ranting again, but this one stung me a bit – stop playing with sharp toys (betas and CTPs) if you do not want to get stung).

Okay, off the tangent and back to the why. As those who have seen me talk know, I am a rabid advocate of Agile development methodologies, in particular Test Driven Development and Refactoring. When you build your software in such a way where the UI is just the UI, it becomes much easier to place tests around the actual moving parts. Why unit tests? Because you are a computer scientist, not a computer artist. Of course, that is not always true, as I have been paid well to repaint ugly art. Surprised If you put your code into classes, you can create tests around it. If you have tests, you have a means of ensuring the quality of your code. This, of course, assumes you are writing the correct tests. And, if you add a test any time a bug is encountered, you can ensure that future changes do not reintroduce that bug either.

MVC in the ASP.NET MVC Framework

When you install the ASP.NET Extensions Preview, you will find a new project type for an MVC ASP.NET website.  To create a new site File >> New Project >> {Choose your language} >> ASP.NET MVC Web Application. When you create this website, you will have the following out of the box:

  • Content folder – Place holder for the CSS file
    • Site.css
  • Controllers folder – Where you place your controllers
    • HomeController.[vb/cs] – Default controller, points to Home Directory under Views
  • Models folder – Where you add models (like DataSets or LINQ to SQL models (dbml))
  • Views – Where you add views, but in a special manner (at least by default)
    • Home Folder
      • About.aspx – about the company view
      • Index.aspx – Index page (default view)
    • Shared Folder
      • Site.Master – Master page for the site
  • Default.aspx page
  • Global.asax file – has the goo for setting up the default routes

ROUTES

The first important concept in the MVC Framework is routes. In order to use MVC, you have to tell the system how to find your bits. Fortunately, there is no work to be done here if you like the default routing mechanism (route controllers to files, by name, in the Controllers folder) and Views to ASPX pages that are named according to the view in directories that match the name of the controller.

Now, open up the Global.asax, and you find the following code:

        protected void Application_Start(object sender, EventArgs e)
        {
            // Note: Change Url= to Url="[controller].mvc/[action]/[id]" to enable 
            //       automatic support on IIS6 

            RouteTable.Routes.Add(new Route
            {
                Url = "[controller]/[action]/[id]",
                Defaults = new { action = "Index", id = (string)null },
                RouteHandler = typeof(MvcRouteHandler)
            });

            RouteTable.Routes.Add(new Route
            {
                Url = "Default.aspx",
                Defaults = new { controller = "Home", action = "Index", id = (string)null },
                RouteHandler = typeof(MvcRouteHandler)
            });
        }

 Look at the first route.

         Url = "[controller]/[action]/[id]",
  1. The item after the first slash in the URL is the controller. In this case, http://www.localhost.com/Home would invoke the Home Controller.
  2. The second item is the action, which means http://www.localhost.com/Home/Index would use the Index method of the Home Controller.
  3. The third item is the ID of the item to display with the method and leads us into models, which I am not ready to talk about.

                Defaults = new { controller = "Home", action = "Index", id = (string)null },

  1. With the pattern controller/action/id, the default controller for the application is Home (HomeController.[cs/vb] in the Controllers folder.
  2. The default action is Index (public void index() {} covered later)
  3. The id is null

                RouteHandler = typeof(MvcRouteHandler)

This is just how it is going to work until you build your own custom route handler(s).

The second route maps Default.aspx to the URL http://localhost/ProjectName/Home/Index. Default.aspx, in this web, is merely a placeholder file. If you delete it, however, it will cause your app to incorrectly render when someone merely types in http://localhost/ProjectName/.

You can set up other routes here if you would like or you can change the custom route to whatever you would like. Note the keywords used, however, as you will have to customize all of this if you want a non-default implementation.

Creating Your Own Controller and View

How do you create a new controller and view? Let’s assume our Controller is named Foo with an action called Bar. To set this up, I need to do the following:

  1. Create an MVC Controller named FooController.[cs/vb] in the Controllers folder (Add >> New Item >> MVC Controller Class)
  2. Create a new folder called Foo under views
  3. Add a new MVC View page to the Foo folder called Bar.aspx

We now have this setup:

  • Controllers
    • FooController.[cs/vb]
  • Views
    • Foo
      • Bar.aspx

One final step here are we are golden. You will have to add the following line to the Index action (highlighted):

namespace MvcApplication1.Controllers
{
    public class FooController : Controller
    {

        [ControllerAction]
        public void Index()
        {
            RenderView("Bar");
        }
    }
}

You can now surf to the URL http://localhost/foo and reach the view (bar.aspx). Pretty simple, eh?

Now for the test. Why is the method named Index? If you will surf back up again, you will remember the following line:

                Defaults = new { action = "Index", id = (string)null },

If we had named a different default, we would use it instead. Note that if you step outside of this box, you will have some manual work to do. Second question: Why am I not surfing to http://localhost/foo/bar? Try it and you will get the following:

Server Error in ‘/’ Application.


An action named ‘Bar’ could not be found on the controller.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: An action named ‘Bar’ could not be found on the controller.

You can fix this, however, by simply adding the following to the FooController:

        [ControllerAction]
        public void Bar()
        {
            RenderView("Bar");
        }

p>Now, the error is gone. Once again, let’s ask WHY? If we go back to the first route, we see this:

         Url = "[controller]/[action]/[id]",

Bar is the action. Okay, so this is pretty inane, but repetition is the key to cementing concepts.

TDD and MVC

As my controller is now a class, I can build tests to test the functionality without having to use funky UI TDD kludges. We will first set up a test around our Index controller action method. This was published earlier in the article, but let’s look at it again.

namespace MvcApplication1.Controllers
{
    public class FooController : Controller
    {

        [ControllerAction]
        public void Index()
        {
            RenderView("Bar");
        }
        [ControllerAction]
        public void Bar()
        {
            RenderView("Bar");
        } } }

Fairly simple controller. We have already covered why the first method is named Index (defaults) and how it renders by default (find the directory Foo, under the Views directory and then the view page Bar.aspx). We have also covered the Bar action (which is not case sensitive in the URL string – just a bit of trivia that you might find very useful).

Now, we create a test stub on the Index method. I can do this in VS 2008 Pro or greater (Team System), but not in the lower SKUs (Express and Standard). If you are playing with Express, download a unit testing framework, like nUnit or mbUnit. To create the test, I am going to right click on the FooController class and choose "Create Unit Tests". It will create me a test that looks like this:

        [TestMethod()]
        [HostType("ASP.NET")]
        [AspNetDevelopmentServerHost("%PathToWebRoot%\MvcApplication1\MvcApplication1", "/")]
        [UrlToTest("http://localhost:64701/")]
        public void IndexTest()
        {
            FooController target = new FooController(); // TODO: Initialize to an appropriate value
            target.Index();
            Assert.Inconclusive("A method that does not return a value cannot be verified.");
        }

This is not really very nice for me, as it is attempting to test the web application. I am not interested in the web app, so let’s clean this up. First, I am going to create a double for the FooController that allows me to find what view we are attempting to render when we call Index. This class inherits from our FooController and looks like this:

    public class FooControllerDouble : FooController
    {
        private string _selectedView;
        public string SelectedView
        {
            get { return _selectedView; }
            private set
            {
                _selectedView = value;
            }
        }

        protected override void RenderView(string viewName
            , string masterName
            , object viewData)
        {
            SelectedView = viewName;
        }
    }

So far, so good. Now we know the correct view when we call index is going to be Bar, so we set up our test. We will prune off everythign but TestMethod() as an attribute and change the internals to use the FooControllerDouble class. Finally, we will add an assert to guarantee the correct view is going to be rendered.

        [TestMethod()]
        //[HostType("ASP.NET")]
        //[AspNetDevelopmentServerHost("%PathToWebRoot%\MvcApplication1\MvcApplication1", "/")]
        //[UrlToTest("http://localhost:64701/")]
        public void IndexTest()
        {
            FooControllerDouble target = new FooControllerDouble(); // TODO: Initialize to an appropriate value
            target.Index(); ;
            Assert.AreEqual("Bar", target.SelectedView);
        }

Running the test, we green light. If you are a TDD purist, you will want to delete the RenderView("Bar") line in the controller and get your red light first. If you are a nazi about it, you will want to delete the method altogether. Angel

From here, we can go into Mocks and Dependency Injection, etc., but I will drop it. It is good enough knowing you can run unit tests without running the web application. And, as you experiment with the MVC Framework, you will find your temptation to stick all of your code in your ASPX pages will go away, as it will not work. Okay, not completely true, but it will stop you from writing all of your application logic in the pages.

MODELS

One final subject in this intro. Models are simply the data you are displaying in your view. Yes, that is an overly simplistic explanation, but let’s role with it, as I do not have time to get any deeper than that. First, let’s create a model. I am going to use AdventureWorks, as it is installed as a sample with SQL 2005 developer when you install samples. You can also download the scripts from CodePlex, although you will need the older ones if you are not playing with SQL Server 2008.

To create the model, I will add a LINQ to SQL class to my Models folder called Contacts. I will then drag the Contact table from the AdventureWorks connection in the server explorer (create one if you have not already) and drop it on the design surface.

To display this data, I am going to create a page called Contacts under the Views/Foo directory (Add >> New Item >> MVC View Page). We will touch this page in a second, but first let’s see how we pass the data. Open the foo controller and add the following: 

        [ControllerAction]
        public void Contacts()
        {
            ContactsDataContextdataContext = new ContactsDataContext();
            RenderView("Contacts", dataContext.Contacts);
        }

To link the model to your view, you can simply pass it in when you call the RenderView method, as in the code above (highlighted). This is the ViewData that will be passed to the page.

Now, to the page. First, open the Contacts.aspx.[cs/vb] page (I am using C#, so mine is .cs). Find the class declaration and add the generic type declaration for what ViewData is. We could simply add the generic declartion for Contacts, like so (highlighted portions added).

using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Views.Foo
{
    public partial class Contacts : ViewPage<Contact>
    {
    }
}

But this is only really good if we are passing a single contact (keep this in mind for your detail page). We are passing in a LINQ list of contacts, so it should be like this (highlighted the additions).

using System.Collections.Generic;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Views.Foo
{
    public partial class Contacts : ViewPage<IEnumerable<Contact>>
    {
    }
}

Now we have the power to run through these contacts. First, add an imports statement to the top of the page (ASPX side):

<body>
    <div>
        <h1>
            Contacts</h1>
        <ul>
            <% foreach (Contact c in ViewData)
               {%>
            <li>
                <%= c.LastName %>,
                <%= c.FirstName %></li>
            <%
                } %>
        </ul>
    </div>
</body>

The page is now bound, although to way too much data (not too worried about that now, as this is a sample). I was working with hooking this up to a control, like a GridView or DataList, but I can’t seem to be left alone to concentrate today, so I am going to kabosh it for now. The issue I am having, at present, is getting the code behind to recognize controls on the page. I just found that Scott Guthrie’s blog has an example with a working Repeater, but I am not having luck hooking it up. Probably something simple, but I will have to play with it later as my cell is ringing again. Arrrggghhhh!!! Open-mouthed

Hope this helps,
Greg