Archive

Archive for the ‘Web Development’ Category

Live Blogging – MSDN Mid-Atlantic Roadshow

September 30, 2008 Comments off

Today I am in Roanoke, VA at the MSDN Mid-Atlantic Roadshow. This Microsoft event highlights Web development and .NET 3.5.

Web Development Basics – 9am

Presented by Andrew Duthie, Microsoft Technology Evangelist. Andrew presents a nice history and overview of web development, from HTML/XHTML, Classic ASP, and up to ASP.NET. It definitely confirms my opinion that I am glad I never was a Classic ASP developer!

He discussed Postback and ViewState, (my least favorite features of ASP.NET and hence my appreciation of ASP.NET MVC.) I know this is not a popular ASP.NET view point, but it makes it difficult for traditional web developers like myself to step into an ASP.NET role. One thing he mentioned was that you can disable ViewState for particular controls, for performance reasons. You would only do this if the element was for display only.

He also discussed one of my favorite features, Master Pages. I have long used this same concept in PHP development and I immediately recognized it in ASP.NET.

Note to self: learn about Membership Profiles. I’ve been developing my own because I am connecting to a non-standard data source (IBM iSeries DB2). Andrew said you can write your own custom backend but still use the built in Profile features.

DataBinding Demo: he showed a typical GridView Control bound to a SqlDataSource. “Declarative Data Binding” – there is no executable code that drives the GridView, it is all expressed in the ASPX. It is fast and easy to develop, but you still have the option to develop your own binding for more control.

Web Services: ASMX and WCF Services both supported. ASMX is simpler, and hosted on IIS, but harder to make cross platform capable. WCF is more complex to configure and can be hosted by any .NET process. ADO.NET Data Services uses WCF. WCF can be used to communicate between servers and applications. “ABC”s of WCF: Address, Binding, Contract. I think it’s time I learned about WCF…

What’s New in the .NET 3.5 Framework for Web Developers and Intro to ASP.NET MVC – 10:40am

Zhiming Xue, Architect Evangelist.

New features introduced in .NET 3.5 SP1: ADO.NET Entity Framework, ASP.NET Dynamic Data, ADO.NET Data Services, ASP.NET Routing.

ADO.NET Entity Framework

Microsoft’s 1st ORM offering for .NET. Designed for providing a UI for ORM development.

  • Entity Data Modle (EDM) separates objects from their Data Structures. Objects are mapped to their physical data store via three things: Conceptual Schema Definition (CSDL), Storage Schema Definition (SSDL), and the Mapping Specification (MSL). This approach decouples the DB Schema from the Application Model. This provides flexibility and can be platform independent (requires an Entity Data Provider.)
  • Entity Framework is a set of services that allow you to consume EDM from within your applications. It includes Object Services, Entity Client, EntitySQL, and Linq-to-Entities.
  • Visual Studio Support is supposed to make the development seamless and simple.

DataSets are raw data store connections. Linq To SQL provides an ADO.NET connection to SqlServer. Entity Framework is going to allow ORM connections to most any database.

DEMO: Z wrote live a WPF application that consumes EDM. Create a WPF solution. Add a DLL project and add a new ADO.NET Entity Model item to the project. Select the data connection and store it in the Web.config file. The database is diagrammed in Visual Studio, complete with relationships. It also creates a Mapping Details window, which he did not demonstrate, but it looks like that is where you change the mapping. The EDMX file contains the XML definition of the SSDL and CSDL. Copy the App.Config file from the EDM project to the WPF project – this links the WPF to the correct Data Store. Add an xxxEntities model object to instantiate the connection. Very fast development, very impressive results in less than 5 minutes!

ASP.NET Dynamic Data

Data driven web application scaffolding. If you are unfamiliar, scaffolding, popularized by Ruby on Rails, provides default pages for Insert, Update, Delete, etc. DD is based on an object model with full controls, metadata, validation, etc. This is expressed in two new ASP.NET project types: Entity Data Model and Linq To SQL.

DEMO: Z added a Dynamic Data Web Application to the above demo so that he could tie in to the same EDM code he already produced. Set the connection stream in the Web.config file to connect the site to the EDM data store. Apparently DD is set up assuming Linq, so Z had to make changes to the Page Templates to use the EDM instead. He had to change LinqDataSource to EntityDataSource. Then he had to register the EDM assembly within the individual pages. (Couldn’t you do this once in Web.config?)

The default scaffolding is very nice and has all the features you would expect. I saw a Routing mechanism, but he did not really discuss how it is used. He demonstrated custom validation. It uses System.ComponentModel.DataAnnotations and implements events for validation.

Overall it looks interesting, but I’m not sure yet how it would be used in a real world setting.

ADO.NET Data Services

Formerly “Astoria”, this technology exposes data in a secure fashion over the web or network. It is a combination of patterns and libraries that enable the creation and consumption of data services for the web as “feeds”. This does not have to be a database: it can be any data source.

  • Implemented as ATOM – tables = feeds, rows = entities. Includes CRUD, is RESTful, and a URI points to a resource.
  • Uses common URL syntax
  • Capable of exposing any object model that contains IQueryable<T>, such as Linq to SQL and EDM.
  • Locked down by default and supports Operation Batching
  • Supports optimistic concurrency

DEMO: Z added a ADO.NET Data Service item to the above Web project. You have to update the service code to indicate what the model is and set some rules. It was a lot of copy and paste and went by too quickly to document. At this point he basically lost me. He hard coded the port the service executed on. He generated a file using DataServiceUTIL.exe (but never executed the app that I saw) and then copied the file into the WPF solution. He added a reference in the XAML to the service and a pointer to the service in App.config. He did finally get it working, and it is interesting, but again I’m not sure how I would use it.

ASP.NET Routing

Routing maps an application URL to specific handlers. I have been using this in ASP.NET MVC for a while, and they have always said that this was not limited to MVC. His example used DynamicDataRoute() instances. At this point his time was running short, so he didn’t really go into a lot of details.

ASP.NET MVC

As we know, MVC has been in my sights for a while now, and I have been very pleased with the implementation. To be fair to Z, he was really rushing to get through this because of time. Unfortunately, I think he skipped a lot of important basics, but he did at least demo the default and the Task List projects. He really skimmed over the project types, and in the long run I think he just confused anyone who was not already familiar with MVC. Last but not least, he only mentioned that you could use Unit Testing, but did not demo it at all.

AJAX Development and Troubleshooting – 1pm

Andrew Duthie presenting. AJAX is a system of lightweight calls to the server without having to repost the entire web page. I have used AJAX extensively in ASP.NET MVC using jQuery.

ASP.NET AJAX

  • Simple Development Framework
  • Represented as additional libraries to ASP.NET
  • Two Models:
  • UpdatePanel Control (zero code implementation)
  • ScriptManager Control (provides a rich framework of JavaScript libraries)

Included with .NET 3.5. AJAX Control Toolkit is a separate project available from CodePlex. The AJAX libraries work on Windows, Mac OS, and Linux in IE, Firefox, Opera, Safari, and others.

DEMO: Andrew created an AutoComplete textbox sample. Create a Web Form and add an AJAX Form to it, which automatically set up the ScriptManager. Add a reference to the AjaxControlToolkit. Now all the Extenders are available in the toolbox. Drag an AutoCompleteExtender to the page and set up a few attributes to hook into a data source. Viola! Good demo.

AJAX updates in .NET 3.5 SP1:

  • Browser History – allows an Ajax page to be bookmarked for future return (including page data)
  • Script Combining – batches a set of Scripts to be treated as a single download

ANNOUNCEMENT: jQuery will be included in all future versions of Visual Studio! It is to be treated as a first class citizen, complete with jQuery support. Microsoft will even have full PSS support. ASP.NET MVC will be the first ship of this feature.

AJAX Troublesooting

While it is a great tool, Visual Studio is not enough. You also need tools for CSS, DOM, and Scripting analysis.

  • The IE Developer Toolbar allows you to drill down into your code and is especially good for IE 6 and IE7. IE8 has built in developer tools including JavaScript debugging, dynamic CSS changes, and more.
  • Firebug is a similar tool for Firefox.
  • Firebug Lite is a tool that can be run without being installed (runs as a JavaScript app.)
  • httpwatch (IE and Firefox Only) – basic is free, pro costs money
  • fiddler – interaction record log

Other Frameworks

Andrew then spent the rest of the session showing some cool AJAX and JavaScript components.

Microsoft Silverlight 2.0

Ashish Jaiman, ISV Architect Evangelist

Silverlight is a cross browser, cross platform .NET plugin for delivering Rich Experiences in a browser.  Silverlight runs in the browser sandbox and executes .NET code.  Can be hosted in any container element in HTML.  HTML can be overlaid on top of Silverlight elements, and you can have many Silverlight components on a single page.

Silverlight 1.0 was only HTML and JavaScript.  Silverlight 2.0, on the other hand, includes a mini CLR, WPF controls, LINQ, collections, media, layout controls, and more.  Silverlight 2.0 has local storage, FileOpen capabilities, sockets, and cross domain HTTP requests.

Silverlight Pros:

  • Video/Audio
  • Enhanced UX to increase stickiness
  • Decrease the learning curve
  • High resolution imagery
  • Data Visualization
  • Leverage .NET Skills for cross browser/cross platform solutions

Silverlight Cons:

  • Requires a browser plugin
  • There is still a learning curve
  • Need for designers to take full advantage

Designer and Developer Collaboration

This brings up one of the main problems with WPF and Silverlight.  Microsoft’s belief is that developers should focus on developing data, communications, business rules, etc.  Designers should be the ones designing our user experiences.  As a one man shop, I can tell you that this isn’t going to happen, but I understand Microsoft’s point.

In order to really maximize the XAML abstraction concept, it will truly take a designer’s touch wrapped around a developer’s logic.  XAML is simply a description of a user interface in XML and contains no code.  A designer can then use tools like Expression Blend (2.5 for Silverlight 2.0) to design the interface, which will then export the design as XAML.  Visual Studio then can read the XAML and allow the developer to add any necessary application logic.  In fact, Blend and Visual Studio can be opened and used simultaneously against the same code, which is more realistic for someone in my shoes.

ASP.NET includes Silverlight support via the <asp:xaml> and <asp:media> tags, Silverlight has web-service support, and it can utilize the Membership, Profile, and Application Service integration.  IIS 7.0 also includes specific support for Silverlight.

Here is a pretty cool Silverlight demo.  (Go to the “Patient Journey Demonstrator”)

Styling and skinning are completely customizable, which is one of the main points of WPF technologies: however you can imagine visualizing your data or application, then you should be able to make it a reality in WPF/Silverlight.

Local Storage

“Cookies on steroids”, local storage provides 1MB of application specific local information.  Can be expanded if the user allows it.  Exposed through Microsoft Isolated Storage.

DOM Integration

Silverlight is still a browser application, so it can interact with and create HTML elements and scripts through .NET code.

Open File Dialog

You can use this to open a local file on the client.

LINQ

Silverlight 2.0 has LINQ support as part of its CLR.  Currently only on IEnumerable<T>, but XLINQ and DLINQ are in development.

Data Acquisition

Silverlight supports the following Methods:

  • GET, POST,
  • Headers
  • Background threads
  • Streaming
  • Cross domain access (ClientAccess.xml, a subset of CrossDomain.xml)
  • WebClient and HttpWebRequest/Response

The session ended when the instructor’s computer went belly up.

Sitepoint's new HTML Reference

March 12, 2008 Comments off

I recently blogged about SitePoint.com releasing its CSS Reference. Today, they released the next great addition to their online reference material, the HTML Reference.

Again, I am impressed by their offering.? It is clean, well thought out, and easy to use.? It is also pretty neat to look at the source code for it: a good model of simple and unencumbered HTML.? The developers at SitePoint really know their stuff!

If you have been following the blog recently, you’ll know that I am very much a nuts and bolts guy when it comes to developing web sites (hence my recent love affair with ASP.NET MVC).? Even so, I frequently forget details when it comes to obscure HTML tags and attributes.? Intellisense support in VS2008 for HTML has been a real help, but you still have to know what the intended results should be. To that end, I expect that I will be visiting this new reference many times.? If you have to write, read, or understand HTML,this resource should definitely be in your library.

Categories: Web Development

ASP.NET MVC Preview 2 Released

March 6, 2008 Comments off

In another case of DGT (Darn Good Timing), in my inbox this morning was my copy of theToques 3320 baixar toques para celular Gratis, toques. Developer Fusion Community Newsletter, and the first item was this announcement. Being a very recent fan of the project, I immediately downloaded and installed the new Preview.? Here are the Release Notes. There are a few breaking changes, mostly object renames, but a little refactoring should take care of the bulk of it.

I spent some time yesterday playing around with it, and I am very happy with what I see. I plan to spend most of today reading Scott Guthrie’s excellent Tutorials.

ASP.NET MVC

March 5, 2008 Comments off

As I posted previously, I’ve been struggling with ASP.NET.? Over the last couple of weeks, I’ve come to acknowledge that at the heart of my struggles is a failure to grasp the logic behind the ASP.NET approach. Of course, begin constantly bitten by newbie bugs is very disheartening for someone with almost ten years of web development, but I have tried to put my pride aside and just come to grips with it. This has been increasingly difficult to do as my frustrations mount, although finding the Wizard control alleviated some of it.

I have been in the process of learning about Data Caching in ASP.NET, which I think will address one of my (many) concerns, but such study requires frequent breaks, during which I usually read some other technical information. It was during one of these breaks yesterday that I picked up the Jan/Feb issue of CoDe: Component Developr Magazine, and doing so may have saved my relationship with ASP.NET.? In it, I came across an article by Jeffrey Palermo entitled “Use the ASP.NET MVC Framework to Write Web Apps without Viewstate or Postbacks” – Note to Jeffrey: bloggers like short titles!? The two page article made me sit up and take notice, and I spent the rest of the day researching ASP.NET MVC.? Championed by none other than Scott Guthrie (ScottGu to his readers), ASP.NET MVC is part of the ASP.NET 3.5 Extensions project hosted at asp.net.? This project was recently released as a CTP and is now available for download.? You can get lots more information about it at Scott’s blog.

By freeing ourselves from the mantra of the PostBack, this MVC approach returns us to real HTML control, without the need to wrap all the content in a runat=server form.? This means you can finally put regular HTML forms on your pages. And best of all, you can still use all the ASP.NET goodies, just in a better architecture: Master Pages, ASP Controls, Code Behind, the works.

Downloading and installing the Extensions CTPwas a snap.? Naturally, it integrates with VS2008, so once it is installed you will see some new project types, a couple of which are MVC specific. Selecting one of these project types will create a project with all the plumbing in place and wired, which I immediately found intuitive and well designed. There are several extra, but well documented, steps you must go through if you wish to add MVC to an existing project, but since I don’t really have any of consequence this was not an issue for me.

Hopefully, this afternoon I will find more time to delve into this further.? I can say that I am very excited by this development.? I can finally do things with ASP.NET that are familiar and comfortable.? Projects like this could easily increase ASP.NET adoption and proliferation. My enthusiastic thanks go to all those involved!

Trudging through ASP.NET

February 19, 2008 Comments off

I just wanted to post a quick update on what’s going on in my world this week.? I posted last week about my Authorize.Net efforts (which I updated this morning).? That work is the precursor to finally learning ASP.NET, one of my New Year’s Resolutions.? I have to admit that I have always assumed that learning ASP.NET would be no big deal.? I have developed web sites in PHP, JSP and Servlets, and even RPG CGI, so what could be so hard about ASP.NET?

Well, the short answer is that it is not hard, however I find myself constantly frustrated because I feel like I have to relearn all the basics.? Seemingly simple matters take me a lot of time and investigation to get working.? I’m sure that if I was learning from scratch this would be no problem, but in my case I am hobbled by too much knowledge going in.? In other words, my brain keeps getting in the way.

So I am trudging through books, websites, and training materials.? Currently, I am reading through Sitepoint.com’s “Build your own ASP.NET 2.0 Web Site“, which appears to be the simplest material I have on hand.? I’m also planning on spending some time going through some beginners videos at asp.net.? And if all that fails, I’ll consider ordering again from TotalTraining.com. I know one day soon I’ll look back on this and wonder what all the fuss was about, but for now I must simply “Soldier On!”

Authorize.net C# Code

February 13, 2008 19 comments

UPDATE 2: The final code for this project is available for download on the Free Code page.


UPDATE: The code for this posting was updated 2-19-2008. I removed the x_password reference. It is not listed in the current documentation, and according to Authorize.Net, the request needs to include the API Login ID and the TransactionCode instead. I also changed isTestMode to IsTestMode for consistency. I also confirmed with them that I need to submit the request from an SSL page, so I am still waiting for that before I can test the code.


My company has an account with Authorize.net, and I am in the process of using it to replace our old PayPal system for online Credit Card purchases. We’ve used their Virtual Terminal system for several years, and once long ago I integrated their CC processing with a PHP site.

I guess it has to do with supplying a ubiquitous solution, but I find that their developer integration tools are somewhat lacking. They have several different methods of submitting and processing payments, and I believe we used SIM (Server Integration Method) previously. In this solution, also my first official foray into the world of ASP.NET, we will be using AIM (Advanced Integration Method) which gives us a much finer level of control over the user experience.

There is a developer’s guide and sample code, but I found the sample code to be lacking in anything terribly useful, like a “sample”. It does not really show you how to send the request or handle the response. I assumed correctly that I am not the first person who wanted a better example, so I hit the Google pavement and found this little gem from 2004 at The Jackol’s Den.

This code gave me a great start, but in looking at it I decided I wanted something a little more flexible. This sample shows all the code in a single method which I assume is supposed to be embedded in an ASP.NET page. I would like to have something more reusable, so I restructured the code a bit.

First, there were a number of items hard coded, such as the Authorize.net version and account information. I could see where you might want this information to be stored in a database or configuration file somewhere, so I put the account information a separate class.

public class AuthNetAccountInfo
{
    public string AuthNetVersion {get; set;}
    public string AuthNetLoginID { get; set; }
    // public string AuthNetPassword { get; set; }
    public string AuthNetTransKey { get; set; }
    public bool IsTestMode { get; set; }
}

Second, some of the actual charge information was hard coded while the rest were passed in to the method as parameters. One item that was hard coded was the description, meaning that this approach would only be good for a single item (either that or the description had to be overly generic). Another is the card number and expiration date! Surely anyone would recognize that this could not go to production, but making it ready for prime time would again mean tying this method to a single page. Parameters such as first name, last name, address, and amount are passed in making the signature of the method long and a little unwieldy. So I created a TransactionRequestInfo class to handle all of these details.

public class TransactionRequestInfo
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
    public string Description { get; set; }

    private decimal _amount;
    public decimal ChargeAmount
    {
        get
        {
            return _amount;
        }
        set
        {
            _amount = Decimal.Round(value, 2);
        }
    }

    private string _zip;
    public string Zip
    {
        get
        {
            return _zip;
        }
        set
        {
            int res;
            if (int.TryParse(value, out res))
            {
                if (res > 99999)
                {
                    throw new ArgumentException("Zip Code Value invalid");
                }
                else
                {
                    _zip = res.ToString().PadLeft(5, '0');
                }
            }
            else
            {
                throw new ArgumentException("Zip code must be numeric");
            }
        }

    }

    private string _securityCode;
    public string SecurityCode
    {
        get
        {
            return _securityCode;
        }
        set
        {
            int res;
            if (int.TryParse(value, out res))
            {
                if (res > 999)
                {
                    throw new ArgumentException("Security Code Value invalid");
                }
                else
                {
                    _securityCode = res.ToString().PadLeft(3, '0');
                }
            }
            else
            {
                throw new ArgumentException("Security code must be numeric");
            }
        }

    }

    private string _cardNumber;
    public string CardNumber
    {
        get
        {
            return _cardNumber;
        }
        set
        {
            long res;
            if (long.TryParse(value, out res))
            {
                _cardNumber = res.ToString();
            }
            else
            {
                throw new ArgumentException("Card Number may only contain numbers");
            }
        }
    }

    private string _expDate;
    public string ExpDate
    {
        get
        {
            return _expDate;
        }
        set
        {
            int res;
            if (int.TryParse(value, out res))
            {
                string exp = res.ToString().PadLeft(4, '0');
                int month = int.Parse(exp.Substring(0, 2));
                int yr = int.Parse(exp.Substring(2, 2));

                if (yr > DateTime.Now.Year ||
                    (yr == DateTime.Now.Year && month >= DateTime.Now.Month))
                {
                    _expDate = month.ToString().PadLeft(2, '0') +
                        "/" + yr.ToString().PadLeft(2, '0');
                }
                else
                {
                    throw new ArgumentException("Expiration Date already passed");
                }
            }
            else
            {
                throw new ArgumentException("Zip code must be numeric");
            }
        }
    }
}

Finally, the original method returned a Boolean indicating whether or not the charge was successful. It does a lot of work deciphering and interpreting the errors and building good error messages, but it writes the message to a Label control. Again, this code is intended for a single page. I felt that we needed a real response mechanism, so I created another class for that as well.

public class TransactionResponseInfo
{
    public string AuthorizationCode { get; set; }
    public string TransactionID { get; set; }
    public string ReturnCode { get; set; }
    public string Message { get; set; }
}

Finally, I made a Transaction class to hold the method and made the method static. As you’ll see, most of the original code remains intact, with the necessary changes to incorporate the new class structure discussed above.

public static class Transaction
{
    public static TransactionResponseInfo ProcessPayment(
        TransactionRequestInfo transaction, AuthNetAccountInfo account)
    {
        TransactionResponseInfo response = new TransactionResponseInfo();

        WebClient objRequest = new WebClient();
        System.Collections.Specialized.NameValueCollection objInf =
          new System.Collections.Specialized.NameValueCollection(30);
        //System.Collections.Specialized.NameValueCollection objRetInf =
        //  new System.Collections.Specialized.NameValueCollection(30);
        byte[] objRetBytes;
        string[] objRetVals;
        string strError;

        #region Set Request Values
        objInf.Add("x_version", account.AuthNetVersion);
        objInf.Add("x_delim_data", "True");
        objInf.Add("x_login", account.AuthNetLoginID);
        // objInf.Add("x_password", account.AuthNetPassword);
        objInf.Add("x_tran_key", account.AuthNetTransKey);
        objInf.Add("x_relay_response", "False");
        objInf.Add("x_delim_char", ",");
        objInf.Add("x_encap_char", "|");

        // Billing Address
        objInf.Add("x_first_name", transaction.FirstName);
        objInf.Add("x_last_name", transaction.LastName);
        objInf.Add("x_address", transaction.Address);
        objInf.Add("x_city", transaction.City);
        objInf.Add("x_state", transaction.State);
        objInf.Add("x_zip", transaction.Zip);
        objInf.Add("x_country", transaction.Country);

        // Card Details
        objInf.Add("x_card_num", transaction.CardNumber);
        objInf.Add("x_exp_date", transaction.ExpDate);

        // Authorization code of the card (CCV)
        objInf.Add("x_card_code", transaction.SecurityCode);

        objInf.Add("x_method", "CC");
        objInf.Add("x_type", "AUTH_CAPTURE");
        objInf.Add("x_amount", transaction.ChargeAmount.ToString());
        objInf.Add("x_description", transaction.Description);

        // Currency setting. Check the guide for other supported currencies
        objInf.Add("x_currency_code", "USD");

        if (account.IsTestMode)
        {
            // Pure Test Server
            objInf.Add("x_test_request", "True");
            objRequest.BaseAddress =
              "https://test.authorize.net/gateway/transact.dll";
        }
        else if (!account.IsTestMode)
        {
            // Actual Server
            objInf.Add("x_test_request", "False");
            objRequest.BaseAddress =
              "https://secure.authorize.net/gateway/transact.dll";
        }
        else
        {
            throw new Exception("Transaction Mode Invalid");
        }
        #endregion

        try
        {
            // POST request
            objRetBytes =
              objRequest.UploadValues(objRequest.BaseAddress, "POST", objInf);
            objRetVals =
              System.Text.Encoding.ASCII.GetString(objRetBytes).Split(",".ToCharArray());

            // Process Return Values
            response.ReturnCode = objRetVals[0].Trim(char.Parse("|"));

            if (objRetVals[0].Trim(char.Parse("|")) == "1")
            {
                // Returned Authorisation Code
                response.AuthorizationCode = objRetVals[4].Trim(char.Parse("|"));
                // Returned Transaction ID
                response.TransactionID = objRetVals[6].Trim(char.Parse("|"));
                strError = "Transaction completed successfully.";
            }
            else
            {
                // Error!
                strError = objRetVals[3].Trim(char.Parse("|")) + " (" +
                  objRetVals[2].Trim(char.Parse("|")) + ")";

                if (objRetVals[2].Trim(char.Parse("|")) == "44")
                {
                    // CCV transaction decline
                    strError += "Our Card Code Verification (CCV) returned " +
                      "the following error: ";

                    switch (objRetVals[38].Trim(char.Parse("|")))
                    {
                        case "N":
                            strError += "Card Code does not match.";
                            break;
                        case "P":
                            strError += "Card Code was not processed.";
                            break;
                        case "S":
                            strError += "Card Code should be on card but was not indicated.";
                            break;
                        case "U":
                            strError += "Issuer was not certified for Card Code.";
                            break;
                    }
                }

                if (objRetVals[2].Trim(char.Parse("|")) == "45")
                {
                    if (strError.Length > 1)
                        strError += "n";

                    // AVS transaction decline
                    strError += "Our Address Verification System (AVS) " +
                      "returned the following error: ";

                    switch (objRetVals[5].Trim(char.Parse("|")))
                    {
                        case "A":
                            strError += " the zip code entered does not match " +
                              "the billing address.";
                            break;
                        case "B":
                            strError += " no information was provided for the AVS check.";
                            break;
                        case "E":
                            strError += " a general error occurred in the AVS system.";
                            break;
                        case "G":
                            strError += " the credit card was issued by a non-US bank.";
                            break;
                        case "N":
                            strError += " neither the entered street address nor zip " +
                              "code matches the billing address.";
                            break;
                        case "P":
                            strError += " AVS is not applicable for this transaction.";
                            break;
                        case "R":
                            strError += " please retry the transaction; the AVS system " +
                              "was unavailable or timed out.";
                            break;
                        case "S":
                            strError += " the AVS service is not supported by your " +
                              "credit card issuer.";
                            break;
                        case "U":
                            strError += " address information is unavailable for the " +
                              "credit card.";
                            break;
                        case "W":
                            strError += " the 9 digit zip code matches, but the " +
                              "street address does not.";
                            break;
                        case "Z":
                            strError += " the zip code matches, but the address does not.";
                            break;
                    }
                }

            }
        }
        catch (Exception ex)
        {
            strError = ex.Message;
        }

        response.Message = strError;

        return response;
    }
}

One of the changes I made was the Test Mode handling. Previously, this was also hard coded, requiring the developer to uncomment certain code to make the service “live”. I felt it would be a good enhancement to make this code driven. This way, the test vs. live status can be switched on and off by the end user (or via configuration). The code uses System.Collections.Specialized.NameValueCollection objects extensively, which I wanted to upgrade to a generic Dictionary<string, string>, but the System.Net.WebClient methods required the old NameValueCollection.

I’m not ready to actually publish this code yet: I haven’t written the code to implement this and it still needs to be tested. If I understand AIM, the request will need to come from a server that has an SSL Certificate installed, which as of yet I do not have. {UPDATE: I rechecked the documentation and it says if you have SSL you “may” use AIM, so perhaps this is optional}

Once I have it all working, I will add it to the Free Code section. In the meantime, feel free to try what is here and let me know your thoughts.

Great new CSS Reference

February 1, 2008 Comments off

I’ve been doing web development for about ten yearsIl regole poker ? un gioco di carte. now and have been a big fan of CSS since about 2000.? I’ve also been a big fan of SitePoint publications since they put out their first book, and I still buy most of their books even though I don’t do as much hands on web development as I used to.

In their blog they recently announced their new free online CSS reference, so naturally I went right over and checked it out.? The site is very well done and has the high level of quality I have come to expect from them. The navigation is good and easy to follow, and the individual property pages are well written.? Each one includes an example and descriptions of all the possible values as well as a grid that shows how well the feature is supported by the various browsers.

If you develop for the web at all, this is a site you must have in your bookmarks.

Categories: Web Development