Charts (Part II)

All right, as promised, here’s the code that gets rid of the jagged edges of the chart we created using Office Web Components. It's hackish, so if you're against that sort of thing, run away.

What we do is basically get the chart as a very large image (1500×1500, for example) and then create a high-resolution thumbnail out of it (300×300, for example) via GDI+. The over-caffeinated reader would wonder why we bothered with office web components in the first place; why didn’t we simply use GDI+ to create the chart? There’s no good reason, really, other than that I wanted to tinker with office web components, which I’ve never used before. ;-) So, without further ado, here’s the code:

//Get the picture
byte[] imageBuffer =
    (byte[])chartSpace.
    GetPicture(“gif”, 1500, 1500);

MemoryStream ms = new MemoryStream(imageBuffer);

Bitmap original = (Bitmap)Bitmap.FromStream (ms, true, true);

//Create the thumbnail Bitmap thumbnail = new Bitmap(300, 300);

Graphics g = Graphics. FromImage(thumbnail);

g.InterpolationMode = InterpolationMode.HighQualityBilinear;

g.DrawImage( original, new Rectangle (0, 0, 300, 300), 0, 0, 1500, 1500, GraphicsUnit.Pixel);

g.Dispose();

//Send the image to the browser Response. ContentType = “image/gif”;

thumbnail.Save (Response.OutputStream, ImageFormat.Jpeg);

Pretty self-explanatory, so I won’t bore you with an explanation.

Encrypting Web.Config

I typically store at least one sensitive item in the web.config file: namely, the connection string to my database. There are several ways to protect your web.config file from falling into the wrong hands (for example, you can explicitly forbid ASP .NET from serving .config files or you can redirect users to a “You stink” page using HttpHandlers). But imagine for a moment that the worst happened and that somehow an attacker got hold of your web.config file. Now what? Obviously, we would like it if sensitive parts of the web.config file look like complete gibberish so that the cracker feels like an utter idiot for wasting all the time trying to get the file.

Encrypting the web.config file is, apparently, not only entirely possible but also ridiculously easy. Enter — drumroll please — aspnet_regiis.

All you need to do is type in…

aspnet_regiis -prov DataProtectionConfigurationProvider -pef [the name of the configuration setting that you want to encrypt; for example, connectionStrings] [location of the folder in which your web.config resides; for example, C:Website1]

–prov — what provider to use

–pef [section name] [location of config file] — what section to encrypt (using the provider mentioned above) and the >location of the .config file

...in cmd prompt and wait a couple of seconds while your configuration file gets encrypted. Load up web.config and you should see something like:

<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAM85VV82faE2ocurvYx6Z4gmoreincomprehensiblegarbagehereitg6XOFiehAkVwulqACFAAAAEZTASYdjIvoIiAR3yzotHc6z8E5</CipherValue>

Accessing the connection string, however, is no different after you encrypt than before. That is, you would still get your connection string as follows:

string connStr=ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

Note that it’s also possible to encrypt web.config programmatically (go down to step5).

Creating Charts with .NET Reports

The Problem

You have a stored procedure that returns the number of products you sold each day from a given date 'til today. You want to allow the user to pick the given date. You're a nice person and figure that you'll make the users' lives easier by showing the data in a nice little graph instead of just dumping the information in an ugly table. But you don't want to spend a lot of time doing this. Oh, and you have to use .NET's Reporting Services because, umm, you have to. ####The Solution

Assuming you already have a shared data source and data set configured and the stored procedure all working:

Drop a chart onto the page from the Toolbox.

Drop the x-axis category (probably the date) into the box below the chart that says "Drop category fields here" and drop your data fields (number of products sold each day, for example) into the box above the chart that says "Drop data fields here."

And that's pretty much it for creating the chart. To allow the user to pick the date: right-click on the document ("document" as in "not the page" as in "the yellow thing and not the white thing") and select "Report Parameters" and enter the name (same as the parameter in the stored procedure), the data type, and the label and that pretty much is it. Go to the "Preview" section and see your chart.

Creating Charts in ASP .NET with Office Web Components

In this article, we’re going to learn how to create the chart shown above on-the-fly using ASP .NET and Microsoft Office Web Components.###Step 1: Add a Reference to Microsoft Office Web Components to the Project

The very first thing to do to use MS Office to create eye-catching charts is to add a reference to the Microsoft Office Web Components dll. So go ahead and create a brand new web project imaginatively called “OfficeWebComponents.” MS Office means COM, so when you go to add a reference, you need to go over to the COM tab. Scroll down until you find the right dll, select it, and click OK.

If you have Office running on the machine, then you probably have this .dll already installed. If you don’t, you will have to get it from Microsoft.

Step 2: Write the Code

Don’t forget to add using OWC11; to your code-behind.

Before I explain it, here’s the code:

public partial class _Default :
 System.Web.UI.Page
{
 protected void Page_Load(object sender,
  EventArgs e)
 {
  string[] chartCategories = new string[]
  {
   “Luke Skywalker”,
   “Mara Jade”,
   “Leia Organa Solo”,
   “Mace Windu”,
   “Han Solo”,
   “Anakin Skywalker”,
   “Depa Billaba”,
   “Yoda”
  };

string[] chartValues = new string[] { “5″, “-50″, “3.5″, “30″, “5″, “-20″, “20″, “0″ };

//The charting component wants its categories and // deliminated values tab. string chartCatsAsString = String.Join(“t”, chartCategories); string chartValuesAsString = String.Join(“t”, chartValues);

//Create the charting workspace OWC11.ChartSpaceClass chartSpace = new OWC11.ChartSpaceClass();

//Create the chart itself OWC11.ChChart theChart = chartSpace.Charts.Add(0);

//Set the type of the chart theChart.Type = OWC11.ChartChartTypeEnum.chChartTypeColumnClustered;

//Add the chart’s title theChart.HasTitle = true; theChart.Title.Caption = "Indecipherable Star Wars Graph";

//Populate the indecipherable data theChart.SeriesCollection.Add(0);

//Add the categories theChart.SeriesCollection[0].SetData( OWC11.ChartDimensionsEnum.chDimCategories, (int)OWC11.ChartSpecial.DataSourcesEnum.chDataLiteral, chartCatsAsString);

//Add the values theChart.SeriesCollection[0].SetData( OWC11.ChartDimensionsEnum.chDimValues, (int)OWC11.ChartSpecial.DataSourcesEnum..chDataLiteral, chartValuesAsString); //Show the chart to the client as a GIF image (400×400)

Response.ContentType = “image/gif”; Response.BinaryWrite((byte[])chartSpace.GetPicture(“gif”, 400, 400)); Response.End(); } }

The code is actually pretty-self explanatory (with my comments at least ;-) ). Rather than bore you by going through the same code again, here’s some information that’s not in the code:

  • You add the chart’s legend the same way you add the title: you set the HasLegend property to true and then set the legend.

  • There are a number of ways to display your chart — everything from pie-graphs to scatter-plots.

  • Your category names and values can’t have any commas in them — the charting component seems to deliminate the string at commas as well as tabs.

  • You can save the chart as an image, too; you aren’t limited to sending the image back to the browser.

  • If you have fewer or more categories than values, you don’t get an error — the chart gets rendered with the extra category/value.

Real Life Uses

In real life, we’re obviously not going to have hard-coded categories and values in your code-behind. We’re probably going to get them from the database. This works just fine. For example, suppose you want to figure out how much time you spent each day working on a certain project. These numbers might be stored in a database or an XML file. All you do is simply read the numbers into a values array, and the days into a categories array; join them into a string just like we did in the example, and then go on from there.

Getting All the Links on a Page

One thing I keep having to do again and again (why???) is extract links from a webpage. I recently created a tiny application that gives you the list of all the links on a given web page, and I thought I’d share it with everyone. Given the url of the page, the first thing to do is to get the source code of the page so that we can screen it for links. There are a couple of ways to do this, but the easiest way, as far as I’m aware of, is to use a WebClient object:

WebClient webClient = new WebClient();

//Get the HTML from the given page byte[] response_html = webClient.DownloadData(url);

UTF8Encoding utf8 = new UTF8Encoding();

string html = utf8.GetString(response_html);

Read more about the WebClient class at MSDN.

Now that we have the source code, the next thing to do is search for all the links. You can do this the hard way — i.e., use the String class’ IndexOf function and hack your way out of the predicaments that come your way (and trust me, there are quite a few of them).

The easy way is to use regular expressions.

The pattern for matching the href = "wherever.whatever" (i.e., the url) part of a link is: href\s=\s(?:"(?<1>[^"]*)"|(?<1>\S+)). Looks a little ugly, but the point is that it works in 90% of the cases. What that regular expression actually means is the subject of another article, but suffice to say, it works.

So, the code then:

private void GetLinks(string url) { //using System.Net WebClient webClient = new WebClient();

     //Get the HTML from the given page
     byte[] response_html = webClient.DownloadData(url);

     //using System.Net
     UTF8Encoding utf8 = new UTF8Encoding(); 

     string html = utf8.GetString(response_html);

//using System.Text.RegularExpressions Regex r = new Regex ("hrefs=s(?:"(?<1>[^"]*)"|(?<1>S+))", RegexOptions.IgnoreCase | RegexOptions.Compiled);

     //using System.Text.RegularExpressions
     //Get all the matches
     MatchCollection mcl = r.Matches(html);

     //using System.Collections
     ArrayList a = new ArrayList(); 

     foreach (Match m in mcl)
         a.Add(m.Value);

//A gridview object grdLinks.DataSource = a; grdLinks.DataBind(); }

7 of 7 pages « First  <  5 6 7

On the Side