Archive

Posts Tagged ‘Web Service’

Invalid JSON primitive in Chrome

24 April 2010 2 comments

I ran into the strangest problem today.  My Ajax call to my web service failed with the error “Invalid JSON primitive”, but only in Chrome…it worked in all my other browsers.

After reading up a bit it seemed to be a problem with the data being sent to the service.  Strange enough I was not sending any…and that turned out to be the problem. 

So for whoever runs into this problem, try setting the data parameter in jQuery to nothing, like in the code below.

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "DataService.asmx/ProjectList",
    dataType: "json", //response type
    data: "{}", // IMPORTANT
    success: function(msg, success) {
        if (success == 'success') {
            //good response
            data = eval(msg.d);
            // attach the template
            $("#slideshow").setTemplateElement('projectFaderTemplate', null, { runnable_functions: true });
            // process the template
            $("#slideshow").processTemplate(msg);
        } else {
            $('#msg').html('Error: ' + msg.d); //service returned an error
        }
    },
    error: function(msg, e) {
        $('#msg').html('Error.  Please contact Technical.'); //error with ajax call
    }
});

Hope this helps someone.

Linq to XML

23 April 2010 Leave a comment

Here is a very short post giving an example on how to use Linq to XML. 

Let’s say we have the following XML

<?xml version="1.0" encoding="utf-8" ?>
<projects>
    <project title="Kraankuil">
        <screenshot>kraankuil.jpg</screenshot>
        <uri>http://www.kraankuil.co.za</uri>
        <technologies>Gimp, ASP.NET, CMS</technologies>
        <launched>12 March 2010</launched>
        <description>Website for a small family owned B&amp;B in South Africa.</description>
    </project>
</projects>

We will do a class to easily handle the data like this

public class Project
{
    public string Title { get; set; }
    public string Screenshot { get; set; }
    public string Uri { get; set; }
    public string Technologies { get; set; }
    public string Launched { get; set; }
    public string Description { get; set; }
}

I will be using this is a web service where I use this code

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<Project> ProjectList()
{ 
    XDocument dataDoc;

    // load the file - from cache if possible
    if (HttpContext.Current.Cache["dataDoc"] == null)
    {
        dataDoc = XDocument.Load(Server.MapPath("~/App_Data/Data.xml"));
        HttpContext.Current.Cache["dataDoc"] = dataDoc; // store it in the cache
    } else {
        dataDoc = (XDocument)HttpContext.Current.Cache["dataDoc"];
    }

    //get the projects from the file
    var projectList = from project in dataDoc.Descendants("project")
                      select new Project
                      {
                          Title = project.Attribute("title").Value,
                          Screenshot = project.Element("screenshot").Value,
                          Technologies = project.Element("technologies").Value,
                          Launched = project.Element("launched").Value,
                          Description = project.Element("description").Value,
                          Uri = project.Element("uri").Value
                      };

    return projectList.ToList();
}

Note: This is NOT a best practices guide so do use common sense, it is only meant to get you started

jQuery and ajax calling webservice

30 August 2009 Leave a comment

In my previous post I wrote a domain name availability checker.  In this post I will create the front-end for it to display the availability using jQuery and ajax.  Note that I changed the web service slightly for this post.  The service will now return ‘available’ or ‘not available’.

I will not be doing much in the sense of validation and will leave that up to you when implementing code.

First off I will add a new HTML (can do webform) file to my solution.  If you do not have jQuery, get it here and rename the downloaded file from .download to .js, then add them to your solution (right-click on the project and click ‘add existing file’, then browse to your jQuery download and add the file.  See image below).

addFile

You can drag the script files from the solution explorer into the header section of your page or add them yourself.  You should then have something along this line:

<head>
    <title>My domain checker</title>
    <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
</head>

We need a text field where the domain will be entered.  If you are not using a plain HTML input, then you will have to do a clever thing later to get the .NET generated name using <%= TextBox1.ClientId %>, so I recommend using a HTML text input if possible.  Add an onkeyup event, I am using onkeyup="getAvailability(displayAvailability, 500);".  The 500 is the delay in ms after the user stopped typing, but more about this later.

Add the following javascript to the page:

    function getAvailabilityTimer() {
        var timer;
        return function(fun, time) {
            clearTimeout(timer);
            timer = setTimeout(fun, time);
        };
    }
    var getAvailability = getAvailabilityTimer();

This will act as the timer since the user stop typing until the ajax callback is made.  You  can change this time by altering the number (500) in the onclick event for the textbox we created above.

The final function is the one that will be doing all the work.  Here is what mine looks like:

function displayAvailability() {
    var domain = $('#domainName').val();
    var selector = "result";//easy to change later
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "DomainService.asmx/CheckDomain", //our service name with the method
        data: "{'domain' : '" + domain + ".com'}", //parameter for which to pass data
        dataType: "json", //responde type
        success: function(msg, success) {
            if (success == 'success') {
                $('#' + selector).html('Domain is ' + msg.d); //good response
            } else {
                $('#' + selector).html('Not able to check at the moment.  Please try again later.'); //service returned an error
            }
        },
        error: function(msg, success) {
            $('#' + selector).html('Not able to check at the moment.  Please try again later.'); //error with ajax call
        }
    });
}

One last thing before testing, in the web service, make sure to uncomment the [System.Web.Script.Services.ScriptService] attribute.  Then let’s start it up and try it out.

checker

And there you have it, working like a charm…I will leave the nice graphicy stuff to you!

When I was testing it the first time, I ran into some problems.  I used nikhilk’s web developer helper.  It is a MUST have when working with ajax.  The problem was that I forgot to set the ScriptService attribute *blush*.

Here is my whole pages’ source: (is the ‘ used right? hope so :))

<head>
    <title>My domain checker</title>
    <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    <style type="text/css">
        body 
        {
            line-height: 25px;
            vertical-align: middle;
        }
        label
        {
            padding-right: 5px;
        }
    </style>
    <script type="text/javascript" language="javascript">
        function getAvailabilityTimer() {
            var timer;
            return function(fun, time) {
                clearTimeout(timer);
                timer = setTimeout(fun, time);
            };
        }
        var getAvailability = getAvailabilityTimer();

        function displayAvailability() {
            var domain = $('#domainName').val();
            var selector = "result";//easy to change later
            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "DomainService.asmx/CheckDomain", //our service name with the method
                data: "{'domain' : '" + domain + ".com'}", //parameter for which to pass data
                dataType: "json", //responde type
                success: function(msg, success) {
                    if (success == 'success') {
                        $('#' + selector).html('Domain is ' + msg.d); //good response
                    } else {
                        $('#' + selector).html('Not able to check at the moment.  Please try again later.'); //service returned an error
                    }
                },
                error: function(msg, success) {
                    $('#' + selector).html('Not able to check at the moment.  Please try again later.'); //error with ajax call
                }
            });
        }
    </script>
</head>

<body>
<div id="result"></div>
<label for="domainName">Domain:</label><input id="domainName" type="text" onkeyup="getAvailability(displayAvailability, 500);" />.com
</body>
</html>

All feedback is appreciated.

Domain name availability checker

25 August 2009 3 comments

I was puzzled about how they do domain name availability checks for some time now.  It was only when I actually needed it for a website that I am doing that I actually looked into this.  This blog entry will cover the basics of getting a domain checker up and running, using a web service to do the actual checking.  I will cover the Ajax part in a next post.

The theory behind it all is actually really simple;  connect to a whois server and do a check on that domain, then check the response for a specific string and voila, we know whether the domain had been registered or not.

First off  create a new ASP.NET project.  Then add a new web service, I called mine DomainService.asmx.

You now got a brand new service with a default HelloWorld method, so the first thing we need to do is replace that with our own method, in this case I’ll call it CheckDomain and pass the domain to check through as a string.

First thing I do is check whether we have some text passed in, if not, throw and exception so that the calling client can handle it.  You might want to do a check first to see whether it is someone else trying to use your service but I won’t cover that here to keep it simple.

Next we need to create a new TcpClient instance.  You should notice when you type the CaSe right, you will get a red accelerator, then click on it (or hit ctrl+. [full stop]) and you will see what appears in the image below, select the using System.Net.Sockets; option.  You can manually add it to the “uses” at the top of the page, but that involves effort :).

AcceleratorOpen

The next thing to do is create a byte[] of the domain and ASCII encode it.  We also need to add the new line and line feed characters to the end of that.

//convert to byte[] to send over stream    
byte[] byteDomain = Encoding.ASCII.GetBytes(domain + "\r\n"); 

Now that we have the domain in an ASCII byte array we can send it to the server, but first we need to create the connection.  Also, a stream is needed to write to the server using our TcpClient connection so we create this as well.  Now lets open the connection, get the stream, write our domain to it, read the response and then close the connection.  I also included some debugging text so we can see the response and make life a little bit easier.

//create connection 
tcpClient = new TcpClient("YOUR_WHOIS_SERVER", 43); 
//get stream
Stream objStream = tcpClient.GetStream(); 
//write to the stream
objStream.Write(byteDomain, 0, byteDomain.Length);
//get response
StreamReader objReader = new StreamReader(tcpClient.GetStream(), 
    Encoding.ASCII); 
//read the response 
response = objReader.ReadToEnd();
#if DEBUG 
    Debug.WriteLine("--[" + domain + "]--"); 
    Debug.WriteLine(response); 
    Debug.WriteLine("--------"); 
#endif 
//close connection 
tcpClient.Close(); 

We now have a response from the server if nothing had gone wrong.  The response can now be analysed for the string.  Note that this response string I am talking about is different for most servers.  Just check through your response and you will find a common string.

//string to return
string returnValue = string.Empty;
//see if it is registered or not
if (Regex.IsMatch(response, "No match for ", RegexOptions.IgnoreCase))
{
    //yes it is registered
    returnValue = "available";
}
else if (Regex.IsMatch(response, "Registrar:", RegexOptions.IgnoreCase))
{
    //no it is not registered
    returnValue = "registered";
}
else
{
    //maybe some error returned from the server, i.e. disconnected 
    throw new Exception("Unknown response from server");
}
return returnValue;

As you probably noticed by now, I love throwing exceptions.  This makes life an awful lot easier when something goes wrong.

Now let’s test this.  Running the webservice (http://localhost:1929/DomainService.asmx in my case) by hitting F5 in Visual Web Developer brings you to the domain page.  Click on the CheckDomain option and enter a test domain (microsoft.com).  If you used the same server as me then you would have gotten (are my tenses right?) an exception, just try a different domain since loads of microsoft.com.* domains exists.  Our company domain works perfect for me, it returns “registered”.

Here is my full source code for this web service

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Net.Sockets;
using System.Text;
using System.IO;
#if DEBUG
    using System.Diagnostics;
using System.Text.RegularExpressions;
#endif

namespace DnsChecker
{
    /// <summary>
    /// Summary description for DomainService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class DomainService : System.Web.Services.WebService
    {

        [WebMethod]
        public string CheckDomain(string domain)
        {
            //some error checking
            if (string.IsNullOrEmpty(domain))
                throw new ArgumentNullException(domain, "Domain was not specified");

            //will contain the response from the server
            string response = string.Empty;
            TcpClient tcpClient = null;
            try
            {
                //convert to byte[] to send over stream
                byte[] byteDomain = Encoding.ASCII.GetBytes(domain + "\r\n");
                //create connection
                tcpClient = new TcpClient("whois.crsnic.net", 43);//possible exception that extension is not in list
                //get stream
                Stream objStream = tcpClient.GetStream();
                //write to the stream
                objStream.Write(byteDomain, 0, byteDomain.Length);
                //get response
                StreamReader objReader = new StreamReader(tcpClient.GetStream(), Encoding.ASCII);
                //read the response
                response = objReader.ReadToEnd();

#if DEBUG
                Debug.WriteLine("--[" + domain + "]------------------");
                Debug.WriteLine(response);
                Debug.WriteLine("---------------------------------------");
#endif
            }
            catch (Exception ex)
            {
#if DEBUG
                Debug.WriteLine("--[" + domain + "]------------------");
                Debug.WriteLine("ERROR FOR " + domain + ex.Message);
                Debug.WriteLine("---------------------------------------");
#endif
                //maybe send some mail in case the whois server is down
                throw;//throw the error after writing the debug info so the client can deal with it
            }
            finally
            {
                //close connection
                tcpClient.Close();
            }

            //string to return
            string returnValue = string.Empty;
            //see if it is registered or not
            if (Regex.IsMatch(response, "No match for ", RegexOptions.IgnoreCase))
            {
                //yes it is registered
                returnValue = "available";
            }
            else if (Regex.IsMatch(response, "Registrar:", RegexOptions.IgnoreCase))
            {
                //no it is not registered
                returnValue = "registered";
            }
            else
            {
                //maybe some error returned from the server, i.e. disconnected 
                throw new Exception("Unknown response from server");
            }
            return returnValue;
        }
    }
}

There you have it, a skeleton web service that checks whether a domain is available or not. You should really update this code and make it safer.  In a next post I will connect this service up to a nice Ajax front end to dynamically check the domain as the user enters it, using jQuery.

This is not guaranteed to be the best way of doing things, but they work for me and others.  Your comments, good or bad, would be greatly appreciated as it helps and inspires me to improve.