Solving the Object Reference Error After Your VS 2013 Publish

After publishing a web application using the VS publish feature, you may receive the infamous “Object reference not set to an instance of an object.” error. And the annoying part is there’s no exact line number that the error is pointing to.

From past experiences, I was able to resolve in one (or more) of the following:

  1. Delete the project DLL, and replace with new DLL (either by publishing or plain FTP)
  2. If you updated a specific page, delete that page, and publish again.
  3. Refresh the application pool (#1 usually takes care of that).

Hope this helps!

Never use SELECT * in SQL Server Views

So, as I discovered, SQL Server kind of “caches” View columns, which can be a problem if you use SELECT *.

Let’s demonstrate:

Create the tables and the view:

CREATE TABLE Categories(CategoryID INT, CategoryName VARCHAR(50))
INSERT INTO Categories
SELECT 1, 'Category1'
UNION SELECT 2, 'Category2'

CREATE TABLE Products (ProductID INT, Description VARCHAR(50), CategoryID INT)
INSERT INTO Products
SELECT 1, 'Product1', 1
UNION SELECT 2, 'Product2', 1
UNION SELECT 3, 'Product3', 2

GO
CREATE VIEW TestView
AS
SELECT c.*, p.Description FROM Categories c JOIN Products p ON c.CategoryID = p.CategoryID
GO

Expected output of SELECT * FROM TestView:

 

 

Now let’s add a column to the Categories table:

ALTER TABLE Categories ADD NewColumn VARCHAR(50) NULL

Output of SELECT * FROM TestView:
Output2

 

 

And… our Description column is showing the data of our NewColumn! As you see, things can get real messy. The best thing would be not to use SELECT * at all, but if it’s too late and you’re seeing the issue described, you can use 2 options to refresh the View metadata and fix the problem:

  1. Use sp_refreshview
  2. ALTER or DROP and RECREATE the View

 

As a side point, it seems SQL Server Management Studio automatically converts SELECT * to individual column names when executing or saving the View in the designer / UI – probably for this reason.

Connecting to External Sql Server from Windows Azure Website

After publishing an application from Visual Studio to a Windows Azure website (which, for the record, was incredibly easy) my website loaded fine, but after trying to login using an external SQL Server it threw me an “Access denied.” error. I resolved that by adding the IP address of the website to the external SQL Server.

The error that came up next was strange. It basically told me that my Stored Procedure which exists does not exist. My connection strings were fine in my application in Visual Studio so I couldn’t imagine what was going on. At last, I decided to check the actual web.config file which was uploaded.

Now, I had 1 Entity Framework connection string in there, with 2 standard SQL Server connection strings.

The EF one looked fine, but the standard ones had the following appended to it:

MultipleActiveResultSets=True;Application Name=EntityFramework

I’m not sure where that came from – I’m assuming it happened in the process of being published – but replacing the altered connection strings with the original, correct ones did the job. I uploaded the newly changed web.config file manually via FTP to ensure it won’t get altered again behind my back.

Hope this helps someone else.

PayPal and Shopping Cart Modification

While building PayPal into an e-commerce project I was working on, I came across a problem scenario as follows:

  1. Customer adds an item to cart.
  2. Customer is redirected to PayPal.
  3. Customer opens cart page in new window, updates cart (i.e. adds new products, ups quantity). (Can happen after #4 too.)
  4. Customer signs in to PayPal, and clicks continue and authorizes the payment, redirected back to your site.

In the above scenario, the customer is able to modify his cart to his likings and then process the order for the original amount when he first clicked the PayPal button. For example, add a $5 product, click the PayPal button, add a $500 product and continue processing the order. Obviously this is a fraud issue; a customer should not be able to manipulate his/her cart after directed to PayPal and able to complete the checkout process this way.

I googled around for solutions to this, and I managed to bring up a few posts addressing, not the exact, but something like the above issue.

  1. https://drupal.org/comment/4652836#comment-4652836 – this post is actually from a Drupal forum, but hints to a solution which is to clear the cart when the user is initially directed to PayPal, with a possible cart restoration *if the user clicks cancel via PayPal*. The drawback with this is if user closes the PayPal page not via PayPal then his/her cart is lost.
  2. Idea inspired from an SO post – compare the current cart amount with the original amount sent to PayPal on the PayPal return URL. If the amounts match, continue to process the order successfully. If the amounts don’t match, then do the following: a. redirect the user to a page explaining what happened. Something like “It seems your cart was modified while your order was being processed by PayPal, and therefore we weren’t able to complete the PayPal checkout process for you. Please return to your cart, make any necessary changes and then try checking out again.”  b. send an email to website admin.

I think approach #2 is the preferred way to go about it. It addresses the issue in a neat and user-friendly way.

 

Amazon Reports API C# Integration

In a previous post I’ve shown how to to submit a feed using the Amazon Feeds API. In this post I’m going to show how to download a report from Amazon using the Reports API. Download the API from the Amazon Developer Home page.

Before we actually download the report, Amazon requires us to submit a request. The time we need to wait after the request until we can download the report varies based on the report type and possibly other factors.

Below are 2 examples of report types:

  • _GET_MERCHANT_LISTINGS_DATA_ – download all inventory.
  • _GET_FLAT_FILE_ORDERS_DATA_ – download orders from specified date.

For readability, I created an Report Type enum, with these report type values, which will be used as part of the argument of the below method. This method requests the report.

public RequestReportResult GetRequestReportResult(ReportType reportType)
{
    RequestReportRequest reportRequestRequest = new RequestReportRequest();
    reportRequestRequest.Merchant = Merchant;
    reportRequestRequest.ReportType = reportType.ToString();

    // If this is an order report, get only last week
    if (reportType == ReportType._GET_FLAT_FILE_ORDERS_DATA_)
    {
        reportRequestRequest.StartDate = DateTime.Now.AddDays(-7);
    }

    return GetClient().RequestReport(reportRequestRequest).RequestReportResult;
}

The GetClient method used here returns a MarketplaceWebServiceClient object. Refer to my previous Amazon post for the code. Also, notice that in the case of a request for an order report, we are setting the StartDate property to specify the date from which we want orders downloaded.

Now we can use this method to get a list of the requests and their statuses:

private List<ReportRequestInfo> GetReportRequests()
{
    GetReportRequestListRequest reportlistReqests = new GetReportRequestListRequest();
    reportlistReqests.Merchant = Merchant;
    GetReportRequestListResponse reportlistResponse = GetClient().GetReportRequestList(reportlistReqests);
    return reportlistResponse.GetReportRequestListResult.ReportRequestInfo;
}

Once the status of our request is _DONE_, we can go ahead and download the report. The data will be saved to a text file. From there you can do whatever you want with it, like import it into your DB.

Here’s the method to download the report. It takes in a RequestReportInfo object (which you get from the GetReportRequests method):

private FileInfo GetReportFile(ReportRequestInfo reportInfo)
{
    GetReportRequest reportRequest = new GetReportRequest();
    reportRequest.Merchant = Merchant;
    reportRequest.WithReportId(reportInfo.GeneratedReportId);

    GetReportResponse reportResponse = new GetReportResponse();

    string path = HttpContext.Current.Server.MapPath("~/Files/Report-" + reportInfo.ReportType + "-" + reportInfo.GeneratedReportId + ".txt");

    using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
    {
        reportRequest.Report = stream;
        reportResponse = GetClient().GetReport(reportRequest);
    }

    return new FileInfo(path);
}

That’s it! Again, there isn’t much documentation on this so I hope this post is found helpful.

Happy Coding!

Amazon Feeds API C# Integration

I’m in the process of building an application which requires strong integration with the Amazon API. I needed to submit product feeds, update inventory and prices, as well as downloading reports and couple other things. When I first was given the project, of course the first I did was a quick google search to see what kind of documentation is out there on the API. There was some info out there (links below), but I had to do a lot playing around first with bits of google searches to get what I needed.

In hopes of making this easier for other Amazon API developers, I’ll outline the basic process for a feed submission and some methods that I’ve ended up integrating into my application using the Amazon Feeds API.

Here’s a few FeedTypes I’ve used.

  • _POST_INVENTORY_AVAILABILITY_DATA_ – update inventory.
  • _POST_PRODUCT_PRICING_DATA_ – update pricing.
  • _POST_PRODUCT_DATA_ – add products to listing.
  • _POST_PRODUCT_OVERRIDES_DATA_ – override info, such as shipping costs.

To get started, you’ll need your Amazon MarketPlaceId, Merchant, Access Key and Secret Access Key, and of course the actual Feeds API.

Note, in the examples posted below, there’s a method called GetClient() which is used. It returns a MarketplaceWebserviceClient object. Looks like this:

private MarketplaceWebServiceClient GetClient()
{
    MarketplaceWebServiceConfig mwsConfig = new MarketplaceWebServiceConfig();
    mwsConfig.ServiceURL = "https://mws.amazonservices.com";
    mwsConfig.SetUserAgentHeader("YourCompany", "1.0", "C#", new string[] { });

    return new MarketplaceWebServiceClient(AccessKey, SecretAccessKey, mwsConfig);
}

I’ve created a generic method to submit all feeds, which goes like this:

public SubmitFeedResult SubmitFeed(FileInfo file, FeedType feedType)
{
    SubmitFeedResponse response = new SubmitFeedResponse();

    SubmitFeedRequest sfrequest = new SubmitFeedRequest();
    sfrequest.Merchant = Merchant;
    sfrequest.MarketplaceIdList = MarketPlaceID;

    using (FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.ReadWrite))
    {
        sfrequest.FeedContent = stream;
        sfrequest.ContentMD5 = MarketplaceWebServiceClient.CalculateContentMD5(sfrequest.FeedContent);
        sfrequest.FeedContent.Position = 0;
        sfrequest.FeedType = feedType.ToString();

        response = GetClient().SubmitFeed(sfrequest);
    }

    return response.SubmitFeedResult;
}

I pass in the file which contains the XML to submit, along with an FeedType enum I’ve declared, which contains my FeedTypes listed above.

Once you submit a feed, you’d want to see the status. Did it go through, were there any errors/warnings etc.

There’s a FeedSubmissionInfo object that returns info for a specific submission. I use this method to return a list of feed submissions.

public List<FeedSubmissionInfo> GetFeedSubmissionList()
{
    GetFeedSubmissionListRequest request = new GetFeedSubmissionListRequest();
    request.Merchant = Merchant;
    GetFeedSubmissionListResponse response = GetClient().GetFeedSubmissionList(request);
    return response.GetFeedSubmissionListResult.FeedSubmissionInfo;
}

You can now get one FeedSubmissionID from one of the FeedSubmissionInfo objects returned, and pass it in to the following method, which will create and return a FileInfo containing the response. You can further modify this to parse out the XML and reformat the text so it’s readable. Change the path to your preferred location for the file to be created to.

public FileInfo GetFeedSubmissionResultFile(string feedSubmissionID)
{
    GetFeedSubmissionResultRequest request = new GetFeedSubmissionResultRequest();
    request.FeedSubmissionId = feedSubmissionID;
    request.Merchant = Merchant;

    GetFeedSubmissionResultResponse response;

    string path = HttpContext.Current.Server.MapPath("~/Files/SubmissionResult-" + feedSubmissionID + ".txt);

    using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
    {
        request.FeedSubmissionResult = stream;
        response = GetClient().GetFeedSubmissionResult(request);
    }

    return new FileInfo(path);
}

That’s the basic process of a feed submission using the Amazon Feed API. You can do plenty more with  the Amazon APIs, like managing orders, prices, inventory, and shipping.

Here are some useful links:

Amazon Developer Home page

XML Documentation

Community Forums

Hope this helps!

Proxy & 504 Response From Server

I had a program which pulled custom-defined data that the user has set and populated a text file with it and uploaded it to an FTP. There were instances where the server would throw a 504 error. I was able to see this with Fiddler – I usually have that open when I program ASP.NET so I can see what’s going on.

The first thing that came to mind was server timing out. I wasn’t exactly sure if this was an ASP.NET page timeout issue or a SQL Server timeout. I extended the CommandTimeout on the SqlCommand and the ExecutionTimeout on the HttpRuntime tag in the web.config. Both didn’t seem to help – I was still getting the 504 response.

All along, I was under the impression that the data wasn’t being returned and that the text file wasn’t being generated. I implemented some logs to see where the code reached and was surprised to find that it had returned the DataTable and generated the file.

At that point, I was a bit confused and googled around for some info that would tell me why a server would return a 504. Google returned some links that were related to 504 and proxies.

That gave me the idea to check my proxy settings.

And… the checkbox was checked. I unchecked it and no more 504 responses.

I don’t know enough about servers and proxies to understand how and why it made a difference, but I maybe this will help others who come across this same problem.

(As a side point, I wonder if the proxy was actually Fiddler’s proxy. Now, that would be ironic.)

Happy coding!