JavaScript appears to be disabled. We recommend you enable JavaScript while visiting this site.

(All original content on this site is licensed under the Creative Commons License Attribution-Noncommercial-No Derivative Works 3.0.)

ASP.NET charts example: Odin Sphere: Part 2 - Parsing the XML

In part one of this series we covered what we'd be doing, and what model we'd be using for the data.

This time we'll parse the XML file that contains the data we need, and populate the objects.

Loading the XML file

The XML file we'll be loading is located at http://jamesrskemp.com/files/OdinSphere.xml, and to keep it simple, we'll load it in assuming we're on a different server/domain.

First we'll need to add the following so we can make use of XDocument.

using System.Xml.Linq;

Next we'll update ProcessRequest by loading the XML file.

XDocument dataFile = XDocument.Load("http://jamesrskemp.com/files/OdinSphere.xml");

And then we'll parse it out into our custom objects.

IEnumerable<Character> characterData = from characters in dataFile.Descendants("Character")
	select new Character {
		Name = characters.Attribute("name").Value,
		HpLevels = (from levels in characters.Element("HP").Element("Levels").Descendants("Level")
			select new HpLevel {
				Level = int.Parse(levels.Attribute("id").Value),
				HitPoints = int.Parse(levels.Attribute("hitPoints").Value)
			}
		).ToList()
	};

With that done, we can now verify the data by displaying some very basic information on the page.

		context.Response.ContentType = "text/plain";
		foreach (Character character in characterData) {
			context.Response.Write(character.Name + Environment.NewLine);
			context.Response.Write("Maximum HP level = " + character.HpLevels.Last().Level.ToString() + Environment.NewLine + Environment.NewLine);

		}

With that aspect verified, we can create and output our graphs, which we'll cover in part three.

Tags: , , ,

Categories: tutorials/guides

(All original content on this site is licensed under the Creative Commons License Attribution-Noncommercial-No Derivative Works 3.0.)

ASP.NET charts example: Odin Sphere: Part 1 - Introduction and model

For a while now I've been meaning to work with ASP.NET 4's built-in charting functionality. While I was going to use it alongside my gas tracking, I think I'm instead going to use my Odin Sphere leveling guide, so I don't have to create an XSLT for the output.

In this part of the series I'll outline the data model I'll be using, and preliminary setups.

Method

So that this can easily be deployed anywhere, I'm going to opt not to use the control itself, but rather programmatically create the charts/graphs. I'll be creating a generic handler (.ashx) to handle the output.

I'll be using LINQ to XML to query the XML file that stores the content and may implement some level of caching at some point.

My environment is Visual Studio 2010 and .NET Framework 4. The controls are available for 3.5 and 2008, however, and 2010 Express should also suffice.

Data model

For this chart I'd like to chart each character's HP progression as they level, with each character displaying on the same graph.

This then gives us a List of Character, with each Character having a Name and a List of HpLevel, with HpLevel containing a Level and a HP total.

In our new Generic Handler (OdinSphere.ashx) we'll add the following within the existing public class:

	/// <summary>
	/// One of the five playable characters in Odin Sphere, for the Playstation 2.
	/// </summary>
	public class Character {
		/// <summary>
		/// Name of the character.
		/// </summary>
		public String Name { get; set; }
		/// <summary>
		/// List of hit point leveling information.
		/// </summary>
		public List<HpLevel> HpLevels { get; set; }
	}

	/// <summary>
	/// Hit point information at a particular level.
	/// </summary>
	public class HpLevel {
		/// <summary>
		/// Level of the character.
		/// </summary>
		public int Level { get; set; }
		/// <summary>
		/// Hit points at a level, for a character.
		/// </summary>
		public int HitPoints { get; set; }
	}

These also require the following:

using System.Collections.Generic;
using System.Linq;

At this point we've got our objects defined and set, so we can grab the data from the XML file and create our necessary objects ... which is exactly what we'll do in the second part of this series.

Tags: , , ,

Categories: tutorials/guides

(All original content on this site is licensed under the Creative Commons License Attribution-Noncommercial-No Derivative Works 3.0.)

Tutorial: ASP.NET (C#) WCF WebHttp service with jQuery: Part 3 - Pulling JSON with jQuery

See the table of contents for more information.

In this series we've started with a new loan class, that contains information about a loan, including the total amount due, how much is to be paid per payment, the interest rate, and etcetera. A method is available that will generate information about the number of payments required to pay off the loan.

In the second part we created a WCF WebHttp service, or a WCF REST service, to use the class/assembly from that loan object and return XML data for GET requests.

In this final part we'll be using jQuery to request information from the service, in JSON format, and display that information to users.

Why JSON?

For maximum flexibility, and because I myself will be hosting the services on their own domain/sub-domain, we'll be taking advantage of jQuery's ability to make JSONP - JSON with Padding - requests, allowing us to pull data, no matter what our domain.

Getting started with jQuery

jQuery is such an advanced library that I can't cover much in this article. See the official jQuery site for more information, including tutorials. For our purposes you'll want to download a copy of jQuery 1.4.2 (or whatever the current release is, assuming things haven't changed too terribly since the time of this writing) for production.

We'll then create a very simple HTML page that we'll modify for our tutorial.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Test page</title>
</head>
<body>
	<div id="pulledData">
	</div>
<script type="text/javascript" src="http://media.jamesrskemp.com/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
	function processData(data) {
		try {
			// JavaScript will go either here - in the *function*
		} catch (ex) {
			alert("Error: " + ex.Message);
		}
	}

	try {
		if ($) {
			// or JavaScript will go here - in the *request*
		}
	} catch (ex) {
		alert("Error: " + ex.Message);
	}
</script>
</body>
</html>

Verifying the service can be called with jQuery, on the same domain

With our base jQuery file, let's verify the Web service, by making a simple request for a loan: http://localhost:49821/FormulasService/Loan?name=asdf&total=4956.24&payment=97.85&yearlyPayments=12&yearlyInterest=4.25 (remember to change the port as needed). Assuming this is running fine, which it should be, we can move onto attempting to query this with jQuery.

In the same project as the above service, add our base html file, from above, and add the following to the second block, making sure that the port is correct.

$.ajax({
	type: "GET",
	url: 'http://localhost:49821/FormulasService/Loan?name=asdf&total=4956.24&payment=97.85&yearlyPayments=12&yearlyInterest=4.25',
	dataType: 'xml',
	success: function (data) { processData(data); }
});

Then add the following to the function.

alert('hey');

So in our first block we're calling the service once the page is ready, and our function on success. The function then gives a very simple alert, so we easily know that the call has succeeded. If we run this on the same domain (localhost and a port), we should get the alert message. However, opening it by itself (by double-clicking on it in Windows Explorer) will result in no messages at all.

Let's tweak this now to use JSON instead. Tweak the second block so that the dataType line is as follows.

dataType: 'json',

In our function, add, or replace the existing alert, with the following:

alert('Loan name: ' + data.Name);

Depending upon the name you've given the loan, you should see an alert message in Chrome or Firefox, with that name. However, if we now try to open this from a different domain, or just via Windows Explorer, we'll see that our loan name is undefined. If we were to look at the response returned from the service, we'd see it's blank.

JSONP

Now let's update the dataType once again.

dataType: 'jsonp',

Refresh now and nothing happens, on anything. However, if we were to take a look at the response we'd see that in fact something is returned, it just happens to be XML, which doesn't help us here. And if we switch the dataType to xml, now we can't use it cross-domain (not to mention we lose out on JSON).

The fix

The fix, found after hours of research and changing settings, requires modifications to our service.

First, let's change the dataType back to JSONP. Since our request no longer passed application/json as an accept-header, the Web service returns the default format, which happens to be XML, which in turn means nothing works. But we can switch the default format type.

Open Web.config in the service and modify the lone standardEndpoint element to the following.

<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" defaultOutgoingResponseFormat="Json"/>

The important part is the new attribute at the end. Build the service and test it again and you'll find that the jQuery called from the same server now works, while the jQuery from a different domain does not.

So we're close, but not quite there.

Localhost no longer

Unfortunately, this is where we can no longer test locally. The missing item is the crossDomainScriptAccessEnabled attribute on the standardEndpoint element.

<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" defaultOutgoingResponseFormat="Json" crossDomainScriptAccessEnabled="true"/>

Since we're authenticated, however, this will horribly fail, which can be shown by just browsing to the service via http://localhost:49821/FormulasService/Loan?name=asdf&total=4956.24&payment=97.85&yearlyPayments=12&yearlyInterest=4.25 and getting a message that "Cross domain javascript callback is not supported in authenticated services."

If you have a server that supports it, go ahead and build the service and push it, with those two new attributes. If you don't, change your jQuery url so that it points to services.jamesrskemp.com, and change the name parameter to your email. (Obviously, if you've pushed the service to your own server, go ahead and use your domain in place of mine.)

Update: Of course, we can also switch off authentication and be able to access this via localhost again. Just add the following to your Web.config within the System.Web element.

<authentication mode="None"/>

With that done you can now refresh either the copy on the same domain, or a local copy, and have the service return the loan name passed.

Now we can modify our function as follows, to get a semi-nice output:

var outputContent = "";
outputContent += "Loan name: " + data.Name + "<br />";
outputContent += "Starting balance: " + data.Total + "<br />";
$.each(data.Payments, function (i, payment) { outputContent += "After a payment of " + payment.Total + ", the remaining amount is $" + payment.LoanRemaining + "<br />";});
$('#pulledData').html(outputContent);

You can see this in action on my media sub-domain, with possible improvements after this article is finished.

And with that, you should have more than enough information to get cracking on your own services, with your own jQuery implementations.

Month List