Follow me on Twitter

First time here?

Check out the Archive, and Subscribe to the RSS feed.

ASP.NET MVC View Page Editor in Visual Studio 2010 Beta 2 won’t recognize HTML tags

This post was written on October 21, 2009 13:24 by MartinHN

I love the new IntelliSense dialog in Visual Studio 2010 Beta 2, that ScottGu has blogged about. But when editing an ASP.NET MVC View Page in Visual Studio 2010 Beta 2, you end up fighting the IntelliSense. That is because IntelliSense and the HTML Editor doesn’t recognize *any* HTML tags.

image

Trying to add a simple paragraph tag in HTML suggests a panel (code snippet). When you finish the P tag, by typing >, the result is this:

image

Pretty annoying to fight with IntelliSense when you want to code! I thought you might be able to fix this, by deleting all the new ASP.NET specific code snippets in the “C:\Program Files\Microsoft Visual Studio 10.0\Web\Snippets\HTML\1033\ASP.NET” folder.

This actually works. Now you can actually see the ASP.NET MVC code snippets, that was hidden in the masses of the ASP.NET ones.

image

But it still has all the ASP.NET Server Controls listed. I thought I could get rid of these by removing a namespace reference to System.Web in the Pages section of Web.config. But that is not present. So I don’t know how to fix that.

Search Twitter from C# using LINQ to XML

This post was written on March 16, 2009 21:28 by MartinHN

In some applications, it could be cool to have a feature that enabled the user to quickly get a glimpse of what people are saying on Twitter about the user or their product, service, company etc.

For instance, a service like GetSatisfaction.com has a feature just like that. They call it Overheard, and this is what it looks like:

overheard

There’s nothing like Twitter to give you feedback. I think MediaTemple felt the effect of unhappy customers on Twitter when their servers broke down, and stayed there for more than two days!

Anyway. I wanted to search from C#, and get back a DataTable. Here’s how it’s done:

    /// <summary>
    /// Searches Twitter for the specified query.
    /// </summary>
    /// <param name="query">The query.</param>
    /// <returns>Returns the search results as a DataTable</returns>
    public DataTable Search(string query)
    {
      DataTable dt = new DataTable();
      dt.Columns.Add("text");
      dt.Columns.Add("html");
      dt.Columns.Add("pubdate");
      dt.Columns.Add("id");
      dt.Columns.Add("link");
      dt.Columns.Add("authorname");
      dt.Columns.Add("authorlink");

      XDocument tweetResults = XDocument.Load(String.Format(
      "http://search.twitter.com/search.atom?q={0}", HttpUtility.UrlEncode(query)));
      XNamespace atomNS = "http://www.w3.org/2005/Atom";
      var q = from tweet in tweetResults.Descendants(atomNS + "entry")
              select new
              {
                Text = (string)tweet.Element(atomNS + "title"),
                Html = (string)tweet.Element(atomNS + "content"),
                DatePublished = DateTime.Parse((string)tweet.Element(atomNS + "published")),
                Id = (string)tweet.Element(atomNS + "id"),
                Link = (string)tweet.Elements(atomNS + "link")
                .Where(link => (string)link.Attribute("rel") == "alternate")
                .Select(link => (string)link.Attribute("href"))
                .First(),
                Author = (from author in tweet.Descendants(atomNS + "author")
                          select new
                          {
                            Name = (string)author.Element(atomNS + "name"),
                            Uri = (string)author.Element(atomNS + "uri"),
                          }).First()
              };
      
      foreach (var item in q)
      {
        dt.Rows.Add(item.Text, item.Html, item.DatePublished, item.Id, item.Link, 
                    item.Author.Name, item.Author.Uri);
      }

      return dt;
    }

Tags: , ,
Categories: C#
Actions: E-mail | Permalink | Comments

Migrate web.config to support the IIS 7 Integrated Pipeline

This post was written on March 15, 2009 22:13 by martinhn

Whenever you deploy a website to IIS 7 that is not compliant with the IIS 7 integrated pipeline, you will get an error like this one:

iis7-integrated-pipeline-error

Not the great error message you get. It actually gives you the solution right away: Migrate Web.config to support the integrated pipeline. To do that, start a command prompt, and execute:

%SystemRoot%\system32\inetsrv\appcmd migrate config "test/"

After doing this, our Web.config is changed to support the IIS 7 integrated pipeline and we can see the website.

Automatically translate Global and Local Resource (resx) files

This post was written on March 13, 2009 22:31 by MartinHN

Yesterday, I blogged about how you can use Google Translate to translate a string in C#. To make it more useful than just a simple translator, and because I need to translate some Global Resource files for an E-commerce website that I’m working on, I wanted to create a small Windows Application in C# that could read a Global Resource file (.resx) and translate it into a selected language using the method for translating a word in C# that i blogged about yesterday.

image

This is how it looks so far. You simply select the resource file you want to translate. Select the current language of the resource file in the middle box, and select the language you want to translate it to in the last box. Click Translate at it should work. The new resource file will be saved in the same location as the application itself.

Translate text in C#, using Google Translate

This post was written on March 12, 2009 00:14 by martinhn

Sometimes, it would be great to be able to translate a text from e.g. English to Danish directly from C#. This could be useful when you want to translate a Resource file into another language.

Google Translate is awesome. There’s also Windows Live Translator, but Microsoft are far behind Google (also) in this game.

Code:

using System;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

namespace Utilities
{
  public static class Translator
  {
    /// <summary>
    /// Translates the text.
    /// </summary>
    /// <param name="input">The input.</param>
    /// <param name="languagePair">The language pair.</param>
    /// <returns></returns>
    public static string TranslateText(string input, string languagePair)
    {
      return TranslateText(input, languagePair, System.Text.Encoding.UTF7);
    }

    /// <summary>
    /// Translate Text using Google Translate
    /// </summary>
    /// <param name="input">The string you want translated</param>
    /// <param name="languagePair">2 letter Language Pair, delimited by "|". 
    /// e.g. "en|da" language pair means to translate from English to Danish</param>
    /// <param name="encoding">The encoding.</param>
    /// <returns>Translated to String</returns>
    public static string TranslateText(string input, string languagePair, Encoding encoding)
    {
      string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", input, languagePair);

      string result = String.Empty;

      using (WebClient webClient = new WebClient())
      {
        webClient.Encoding = encoding;
        result = webClient.DownloadString(url);
      }

      Match m = Regex.Match(result, "(?<=<div id=result_box dir=\"ltr\">)(.*?)(?=</div>)");

      if (m.Success)
        result = m.Value;

      return result;
    }
  }
}

The translated string is fetched by the RegEx close to the bottom. This could of course change, and you have to keep it up to date.

ASP.NET Search Engine Optimization

This post was written on March 11, 2009 17:46 by martinhn

I made a few E-commerce websites a few years back when I was self-employed. Ranking well in the search engines is very important for E-commerce websites in order to get relevant visitors, and if your site is designed well for converting, visitors into sales, you will make money. That’s the way it goes.

A lot of naive CEO’s and alike, think that you absolutely have to hire expensive SEO consultants in order to rank well. That is *not* true. Instead, why don’t you just spent your time and money on making original, relevant and great content? That’s a true winner.

Though, there’s still a few technical details you have to get right.

Make sure to set a unique page title on all your pages. Use the same text as a <h1> tag on the page.

Don’t screw up your URLs. You will get punished having the same content on those URLs: www.example.com/producs/computers?sortorder=price&page=2 and www.example.com/producs/computers?page=2&sortorder=price. This is called duplicate content, and search engines doesn’t like that. You can use the new canonical tag for telling search engines which one is original.

Make internal links absolute. Yes. You shouldn’t do this: <a href=”/page1.htm”>Page 1</a>. Do this instead: <a href=”http://www.example.com/page1.htm”>Page 1</a>.

301 permanent redirect example.com to www.example.com or vice versa. Allowing visitors to access your page on both URLs, will also be treated as duplicate content.

If you’re moving your website to a new platform, server, technology and your URLs will change. Make sure not to return 404 on the old URLs. You have to 301 permanent redirect the old URLs to the new ones. Otherwise you will lose all your current search engine carma.

I use those two methods to set page information, and 301 redirect:

  private void SetMetaInformation()
  {
    this.Title = PageTitle;

    HtmlMeta metaKeywords = new HtmlMeta();
    metaKeywords.Name = "keywords";
    metaKeywords.Content = this.MetaKeywords;
    this.Header.Controls.Add(metaKeywords);

    HtmlMeta metaDescription = new HtmlMeta();
    metaDescription.Name = "description";
    metaDescription.Content = this.MetaDescription;
    this.Header.Controls.Add(metaDescription);

    HtmlMeta metaRobots = new HtmlMeta();
    metaRobots.Name = "robots";
    metaRobots.Content = this.MetaRobots;
    this.Header.Controls.Add(metaRobots);
  }

  public void PermanentRedirect(string newUrl)
  {
    Response.Status = "301 Moved Permanently";
    Response.StatusCode = 301;
    Response.AddHeader("Location", newUrl);
  }
 
 

You also want to take a look at the Google SiteMap.

Create a generic handler in ASP.NET and call it sitemap.ashx. Generate and XML string like this:

 
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <url>
      <loc>http://www.example.com/</loc>
      <lastmod>2005-01-01</lastmod>
      <changefreq>monthly</changefreq>
      <priority>0.8</priority>
   </url>
</urlset> 

 

Take a further look at the importance of sitemaps, if you want to know why you should use one.

Tags: , ,
Categories: ASP.NET
Actions: E-mail | Permalink | Comments

C# TwitPic API client

This post was written on March 10, 2009 22:51 by martinhn

I’ve spent some time lately, playing around with the Twitter API. And along with that belongs the TwitPic’s API. I’m using Twitter a lot, to stay in touch with tech news, other developers and just for fun. But it’s getting more and more used for a lot of different things, and I needed it to integrate with an E-commerce platform I’m developing.

The code for post a picture to TwitPic looks like this:

    /// <summary>
    /// URL for the TwitPic API's upload method
    /// </summary>
    private const string TWITPIC_UPLADO_API_URL = "http://twitpic.com/api/upload";

    /// <summary>
    /// URL for the TwitPic API's upload and post method
    /// </summary>
    private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://twitpic.com/api/uploadAndPost";

    /// <summary>
    /// Uploads the photo and sends a new Tweet
    /// </summary>
    /// <param name="binaryImageData">The binary image data.</param>
    /// <param name="tweetMessage">The tweet message.</param>
    /// <param name="filename">The filename.</param>
    /// <returns>Return true, if the operation was succeded.</returns>
    public bool UploadPhoto(byte[] binaryImageData, string tweetMessage, string filename)
    {
      // Documentation: http://www.twitpic.com/api.do
      string boundary = Guid.NewGuid().ToString();
      string requestUrl = String.IsNullOrEmpty(tweetMessage) ? TWITPIC_UPLADO_API_URL : TWITPIC_UPLOAD_AND_POST_API_URL;
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
      string encoding = "iso-8859-1";

      request.PreAuthenticate = true;
      request.AllowWriteStreamBuffering = true;
      request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
      request.Method = "POST";

      string header = string.Format("--{0}", boundary);
      string footer = string.Format("--{0}--", boundary);

      StringBuilder contents = new StringBuilder();
      contents.AppendLine(header);

      string fileContentType = GetImageContentType(filename);
      string fileHeader = String.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", "media", filename);
      string fileData = Encoding.GetEncoding(encoding).GetString(binaryImageData);

      contents.AppendLine(fileHeader);
      contents.AppendLine(String.Format("Content-Type: {0}", fileContentType));
      contents.AppendLine();
      contents.AppendLine(fileData);

      contents.AppendLine(header);
      contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "username"));
      contents.AppendLine();
      contents.AppendLine(this.Username);

      contents.AppendLine(header);
      contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "password"));
      contents.AppendLine();
      contents.AppendLine(this.Password.ToInsecureString());

      if (!String.IsNullOrEmpty(tweetMessage))
      {
        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "message"));
        contents.AppendLine();
        contents.AppendLine(tweetMessage);
      }

      contents.AppendLine(footer);

      byte[] bytes = Encoding.GetEncoding(encoding).GetBytes(contents.ToString());
      request.ContentLength = bytes.Length;

      using (Stream requestStream = request.GetRequestStream())
      {
        requestStream.Write(bytes, 0, bytes.Length);

        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
          using (StreamReader reader = new StreamReader(response.GetResponseStream()))
          {
            string result = reader.ReadToEnd();

            XDocument doc = XDocument.Parse(result);

            XElement rsp = doc.Element("rsp");
            string status = rsp.Attribute(XName.Get("status")) != null ? rsp.Attribute(XName.Get("status")).Value : rsp.Attribute(XName.Get("stat")).Value;

            return status.ToUpperInvariant().Equals("OK");
          }
        }
      }
    }
Tags: , ,
Categories: C#
Actions: E-mail | Permalink | Comments

ASP.NET MVC and Classic ASP

This post was written on February 2, 2009 00:09 by martinhn

As I pointed out in my blog post a few days ago, I see several reasons why you should make the switch to ASP.NET MVC. On the other hand, you have to remember that ASP.NET WebForms has been around for many years, and is a very mature technology. We all know that new technology has its initial flaws.

I was fooling a little around with the technology, specifically some databinding where I had a DataTable and wanted to display a Table with the contents. My instant thought was: “This is like databinding back in the days of Classic ASP”…

Take a look at this:

<html>
<head>
<title>Get data from database</title>
</head>
<body>
<%
' Data connection
Set Conn = Server.CreateObject("ADODB.Connection")
DSN = "DRIVER={Microsoft Access Driver (*.mdb)}; "
DSN = DSN & "DBQ=" & Server.MapPath("/cgi-bin/database.mdb")
Conn.Open DSN

' SQL statement
strSQL = "Select * from Employees"
Set rs = Conn.Execute(strSQL)

Do

   Response.Write rs("Test") & "<br>"

   rs.MoveNext

Loop While Not rs.EOF

Conn.Close
Set Conn = Nothing
%>
</body>
</html>

Good old Classic ASP that is. You’ve got to admit that you had seamless control of the HTML that was being rendered!

Which is also the case with ASP.NET MVC. MVC offers you control and simplicity, as opposed to WebForms where you place a server control on the form, and sometimes you ended up with your HTML a complete mess…

Of course, MVC is a lot more maintainable and structured, than Classic ASP was. You instantly get a separation of concerns with the Model, View and Controller design pattern.

So we can fetch data in our Controller:

    public ActionResult Index()
    {
      DataTable dt = new DataTable();
      dt.Columns.Add("Column1");

      dt.Rows.Add("Test 1");
      dt.Rows.Add("Test 1");
      dt.Rows.Add("Test 1");
      dt.Rows.Add("Test 1");
      dt.Rows.Add("Test 1");
      dt.Rows.Add("Test 1");

      ViewData.Model = dt;
      
      return View();
    }


And display it, somewhat like we did back in the days of Classic ASP:

<% foreach (System.Data.DataRow item in ((System.Data.DataTable)ViewData.Model).Rows) 
   { %>
    <%= Html.Encode(item[0].ToString()) %><br />
<% } %>

 

To be honest, I actually likes going back to basics and getting full control of my HTML. Working in WebForms, you sometimes search for control settings to enable or disable the rendering of a certain piece of HTML. I think it is a lot easier to just give you full control.

But on the other hand, I could easily see a lot of the Classic ASP ‘bad habits’ return. Classic ASP can be *ugly* as hell, which means the maintainability is very poor. The same could happen with MVC if you aren’t disciplined enough. WebForms sort of put you in a box, but you could still make it look pretty ugly as well…

ASP.NET MVC Release Candidate links

ScottGu’s release candidate blog post 

Stephen Walther’s guide to learning ASP.NET MVC

Tags: ,
Categories: ASP.NET
Actions: E-mail | Permalink | Comments

Is the use of AJAX on the web voting for a change to ASP.NET MVC?

This post was written on January 30, 2009 00:13 by martinhn

With ASP.NET MVC in Release Candidate now, the technology is getting a lot of attention these days. I personally haven’t given it any greater thought until just recently, but I have to admit that I’m tempted towards a change. I like ASP.NET WebForms. I think the WebForm approach provides us with great manageability and gives us a very rich set of controls.

But one thing that I don’t like about WebForms is, that it abstracts the anatomy of the web and how the web works. This was probably done to lure WinForms developers towards web development and making the change as easy as possible. But I think developers learning ASP.NET WebForms is missing out on the core web technology that is request, responses and headers etc. If you don’t know the core elements of what you’re working with, you can easily make some terrible mistakes.

As user experience is getting much more focus today, especially in the business of SaaS products, you have to deliver a great deal of responsiveness through the use of AJAX. In ASP.NET WebForms I see myself ending up rendering the page once, and doing AJAX callback through the core XmlHttpRequest in JavaScript when the user makes a change to some data. That’s to avoid postbacks. By doing this, I’m missing out on ViewState as well and what is left of ASP.NET WebForms now?

I think the high demand of quality (Testability) and user experience (Responsiveness = AJAX) is making ASP.NET WebForms obsolete.

I see several good reasons to dump WebForms for MVC:

  • - AJAX is used all over, so what good is postback, ViewState and the Page life cycle?
  • - WebForms is making your HTML look very ugly, especially because of the ViewState hidden field.
  • - ViewState can get very large, and slow down your pages.
  • - Performance is better on MVC –> You can handle more requests per second.
  • - The ability to test your code is better on MVC.

Initially, it looks like MVC is missing out on the rich set of controls that ASP.NET WebForms have. But I think this need will be driven by the awesome community that .NET have.

Tags: ,
Categories: ASP.NET
Actions: E-mail | Permalink | Comments

Early thoughts on Windows Azure

This post was written on October 27, 2008 17:53 by martinhn

Windows Azure, Windows en la nubeSo I just got home from work, and fired up my browser to check out the latest news from this year’s Microsoft PDC, by live streaming, and following the live blogging session. And as always, something big is underway. Windows Azure, is Microsoft’s answer to Amazon EC2. It is a cloud computing platform on Microsoft technology.

I’m truly thrilled by the thought. This gives me great possibilities. As an entrepreneur, I get loads of ideas. My biggest pain is always how to deploy this. Funding is a big issue, and this leads to compromises in server infrastructure and stuff. As a developer, I’m not that much focused on servers and thing alike, so to have a big platform is an advantage.

At PDC2008, they showcased a mobile app called Bluehoo. On stage, by editing an XML file online he scaled his platform from 1 to 20 nodes to be capable of the upcoming load due to the the announcement made at PDC.

My thoughts on pros:

  • Great scalability
  • Large content network = low latency around the world
  • Consolidation
  • Pay as you go premise – compared to buying hardware upfront
  • Easy application maturing – developing locally, deploying to a staging environment before deploying to production

Cons:

  • The inevitable: “What will they do with my data?”
  • Dependency on Microsoft
  • Unawareness – like deploying your app to ‘a black box’

On the Windows Azure site, the links to SDK’s and VS2008 tools are broken. They should be good shortly!

Update: For more information on Windows Azure, check out this blog post at Channel 10.

Or this: http://blogs.zdnet.com/microsoft/?p=1671

 

Powered by BlogEngine.NET 1.5.1.24

About the author

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

© Copyright 2009