Tuesday, July 28, 2015

WCF Service to Internet

 
 
Here are the steps to convert the WCF Service to be accessed from the browser over the internet.
 
1. Add the 'WebGet' parameter to the interface.
2. Add the endpoint binding to the Web config file.
3. Add the endpoint behavior to the Web config file.
 
Now the service should be exposed over the internet.
    
[ServiceContract]
    public interface IServiceSomeName
    {
        [WebGet(UriTemplate = "gettoken", ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        string GetToken();
        [OperationContract]
        string GetData(int value);
 
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
        // TODO: Add your service operations here
    }
    <services><service name="WcfServiceSomeName.ServiceSomeName">
        <endpoint binding="webHttpBinding" contract="WcfServiceSomeName.IServiceSomeName"  behaviorConfiguration="webHttp"/>
      </service>
    </services>
 
 
 
 
      <endpointBehaviors>
        <behavior name="webHttp">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
 Also I noticed one more interesting fact.
Quote
- WCF Data Services don't support passing parameters in the request body or headers, they have to be present in the URL of the request. This makes it hard to pass long values.

Unquote
I found this info in the below link.
 
 
Hope these tips will come in handy when working with WCF web services.
Cheers
Adam
 
 

Sunday, June 21, 2015

Tips on JSON and SQL Geography


Here is one way to get key and value attributes from a JSON string which contains the Key and Value attributes in JSON string format.


    var regex = new RegExp('"', 'g');
    $.each(jsonValues, function () {
        newhtml += "<tr>";
        newhtml += s + KeyandValue[0].toString().replace(regex ,'') +e;
        newhtml += s + KeyandValue[1].toString().replace(regex ,'') + e;
        newhtml + "</tr>";
    })
 
 

Here is one tip to convert between DBGeography and SQLGeography

//SqlGeography theGeography;
int srid = 4326; // or alternative
DbGeography newGeography = DbGeography.FromText(theGeography.ToString(), srid);

 
//To reverse it:
DbGeography theGeography;
SqlGeography newGeography = SqlGeography.Parse(theGeography.AsText()).MakeValid();


 
Happy coding.
 
 

Monday, May 25, 2015

Using SQL Spatial to create polygon features

I was assigned a task to generate polygon features using SQL Spatial. SQL Spatial has many features to create geometric/geographic features. When I was working on this assignment , for some reason, some of the generated polygons were not appearing correctly. They were too big or it didn't look right.

For example, when I tried to generate all the US state polygons, some states showed up correctly but some was too big and not of the right size.

After doing some searching, I found out that the polygons are not drawn in the right orientation.

I checked the envelope angle of each polygon feature using the following command.

EnvelopeAngle

If the envelope angle is greater than 180 degrees then I re-oriented the polygon using the following command

ReorientObject

After this fix, then all the 'Polygons' showed up correctly.

Hope this tip helps.

Have fun coding.

 

Wednesday, April 29, 2015

Using Open Layers to display Map

Here is a simple example on how to load a map using "Open Layers" open source GIS API.

==== JavaScript Code ========

$(document).ready(function () {

LoadMap();

}); 


function LoadMap() {

var map = new ol.Map({

target: 'map',

layers: [


new ol.layer.Tile({

source: new ol.source.MapQuest({ layer: 'sat' })

})

],


view: new ol.View({

center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),

zoom: 4

})

});

}

=================================================

======== Code from Index.html =============================

<link rel="stylesheet" href="http://openlayers.org/en/v3.2.1/css/ol.css" type="text/css">

<script src="http://openlayers.org/en/v3.2.1/build/ol.js" type="text/javascript"></script>

<script src="scripts/mainJavaScript.js"></script>

<div id="map" class="map"></div>

============================================================

These lines should display a "World Map".

Happy Coding.

Cheers
Adam




 

Saturday, March 28, 2015

Convert Scientific Notation String to Double in c#


I was working with conversion of some scientific notation numbers like this "2.09550901805872E-05" which was represented in string to double.
 
When I did that using regular ToConvert function , it was throwing an exception.
 
After few research, I found out that it should be done using Parse function and NumberStyles as shown below.
 
Double.Parse("<Scientific Exponent String>", NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
 
Hope this tip helps.
 
Cheers
Adam

Friday, February 27, 2015

Calling MVC Server Side Function without using JQuery



I have a Web Method, which is part of my MVC controller.

       [HttpPost]        public JsonResult AddProduct(string productName, string productPrice)
        {
            JsonResult togoValue = new JsonResult();
            try
            {
                Product newProduct = new Product(productName, Convert.ToDouble(productPrice));
                if (newProduct.IsDuplicate() == false)
                {
                    newProduct.Save();
                }
                else
                {
                    throw new Exception("Product with same name and price already exists!");
                }
                togoValue = Json(InMemoryDB.GetAllRecordsinJSONFormat());
            }
            catch (Exception ex)
            {
                togoValue = Json("Error : " + ex.Message.ToString());
            }
            return togoValue;
        }


Examine the highlighted items above.  

HttpPost - This keyword mentions this method can be called only by a POST call.
JsonResult - This is the return type of the web method.
productName and productPrice - These are the input arguments of two different types.

I am calling this server side function using the following JavaScript call without using JQuery.

       function SendProducttoServer(inProdName, inProdPrice) {
            var newProduct = "productName=" + inProdName + "&productPrice=" + inProdPrice ;            var xmlhttp = new XMLHttpRequest();
            if (xmlhttp == null) {
                alert("Browser does not support XMLHttpRequest.");
            }
            else {
                xmlhttp.onreadystatechange = function () {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                        if (xmlhttp.responseText.indexOf("Error") > -1)
                        {
                            ShowUserMessage(xmlhttp.responseText);
                        }
                        else
                        {
                            ShowUserMessage("Added new record !");
                            var allRecords = JSON.parse(xmlhttp.responseText);
                            UpdateTable(allRecords);
                        }
                    }
                }
                xmlhttp.open("POST", "/Default/AddProduct", true);
                xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                xmlhttp.send(newProduct);

            }
        }


Note the highlighted items in the above JavaScript function. This function performs a POST call and submits the arguments to the Server Side Function.

This type of calling will come in handy if the client insists not to use JQuery or other third party scripts.

Happy Coding !

Cheers
Adam

Sunday, January 25, 2015

Using POST when connecting to remote ASP.NET API Web Service


ASP.NET API Web Service web method calls can be modified to receive POST input. The reason is , sometimes we may need to pass sensitive information like password or other information. There are many ways to do this. Here is a new technique which I used.

=============


        [HttpPost] (This attribute is required to tell the WebMethod is a POST.)
        [ActionName("login")]
        public ManagerOutput getUserInfo(HttpRequestMessage inmessage) (The whole request is being used as input.)
        {
            ManagerOutput output = new ManagerOutput(); (This is the output the methos will send.)
            output.operation = "login";
            try
            {
                var theRequestBody = "";
                try
                {
                    theRequestBody = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(theRequestBody)); (The whole request can be passed in encoded 64 bit. Here it is being decoded. So the information sent is not visible easily.)
                    theRequestBody = inmessage.Content.ReadAsStringAsync().Result; (This is where the message content (body) is extracted from the request string.)
                }
                catch(Exception ex)
                {
                    throw new Exception("Error in ReadAsStringAsync." + ex.ToString());
                }
                if (theRequestBody == null)
                   throw new Exception("theRequestBody is null");
                ModelUserPin objModelUserPin = new ModelUserPin();
                try
                {
                    objModelUserPin = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<ModelUserPin>(theRequestBody); (This is where JavaScript JSON content is converted to CSharp class. Here the class name is ModelUserPin.)
                }
                catch (Exception ex)
                {
                    throw new Exception("Error in JavaScriptSerializer." + ex.ToString());
                }
 
                // Add more business logic here.

                //return Newtonsoft.Json.JsonConvert.SerializeObject(output); (If required the CSharp class can be converted to JSON string.)

                return output; (When returning the results , the whole CSharp class is sent out.)
            }
            catch (Exception ex)
            {
                output.status = "ERROR: " + ex.ToString();
                //return Newtonsoft.Json.JsonConvert.SerializeObject(output);
                return output;
            }
        }

 =============
When calling this function from the JavaScript side, this is the code to use.
=======
this.validateUser = function (username, pin) {
    console.log('validateUser');
    var bodyContent  = Base64.encode( JSON.stringify({ "userId": username, "userPin": pin }) ); (This is where the request is encoded.)
    var url = urlBase + loginUserURl;
    $.ajax({
        url: url,
        type: 'POST',
        dataType: 'json',
        timeout: 60000,
        data: bodyContent,
        contentType: 'application/json; charset=utf-8', (This content type is important. Then only the JavaScript will encode the csharp class coming from the Web Service. Else the control will goto error: instead of success:)
        error: function (errData) {
            validateUserFailedCallback(errData);
        },
        success: function (data) {
            validateUserCallback(data);
        }
    });
};

Here is the value for Base64 used in the code above.


// Create Base64 Object

var Base64 = { _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", encode: function (e) { var t = ""; var n, r, i, s, o, u, a; var f = 0; e = Base64._utf8_encode(e); while (f < e.length) { n = e.charCodeAt(f++); r = e.charCodeAt(f++); i = e.charCodeAt(f++); s = n >> 2; o = (n & 3) << 4 | r >> 4; u = (r & 15) << 2 | i >> 6; a = i & 63; if (isNaN(r)) { u = a = 64 } else if (isNaN(i)) { a = 64 } t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a) } return t }, decode: function (e) { var t = ""; var n, r, i; var s, o, u, a; var f = 0; e = e.replace(/[^A-Za-z0-9\+\/\=]/g, ""); while (f < e.length) { s = this._keyStr.indexOf(e.charAt(f++)); o = this._keyStr.indexOf(e.charAt(f++)); u = this._keyStr.indexOf(e.charAt(f++)); a = this._keyStr.indexOf(e.charAt(f++)); n = s << 2 | o >> 4; r = (o & 15) << 4 | u >> 2; i = (u & 3) << 6 | a; t = t + String.fromCharCode(n); if (u != 64) { t = t + String.fromCharCode(r) } if (a != 64) { t = t + String.fromCharCode(i) } } t = Base64._utf8_decode(t); return t }, _utf8_encode: function (e) { e = e.replace(/\r\n/g, "\n"); var t = ""; for (var n = 0; n < e.length; n++) { var r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r) } else if (r > 127 && r < 2048) { t += String.fromCharCode(r >> 6 | 192); t += String.fromCharCode(r & 63 | 128) } else { t += String.fromCharCode(r >> 12 | 224); t += String.fromCharCode(r >> 6 & 63 | 128); t += String.fromCharCode(r & 63 | 128) } } return t }, _utf8_decode: function (e) { var t = ""; var n = 0; var r = c1 = c2 = 0; while (n < e.length) { r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r); n++ } else if (r > 191 && r < 224) { c2 = e.charCodeAt(n + 1); t += String.fromCharCode((r & 31) << 6 | c2 & 63); n += 2 } else { c2 = e.charCodeAt(n + 1); c3 = e.charCodeAt(n + 2); t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63); n += 3 } } return t } }
=======

Also when debugging / testing the code , make sure to POST to http site and not to a https (SSL) site. If you attempt to POST from http to https , it will abort and throw error. It will not even POST.
 
Hope the tips mentioned here, helps you in your project.
Thanks
Adam
 
 
 

Thursday, December 25, 2014

Issues observed in "ESRI GeoEvent Processor"


 
When working with "ESRI GeoEvent Processor", I noted couple of issues.

Issue 1 :

If the "ESRI GeoEvent Processor" service is updating or adding new GIS features based on the "GeoEvent", it will work fine for few hours and then the server performance will be extremely slow and will become unusable at some time. Then we have to either restart the GEP Service and ArcGIS Server Service or restart the server itself.

After some trial and error, I found out that, if the "ArcSDE" data is a "Versioned" data then this issues happens. In the "Unversioned" ArcSDE data this will not occur.

Issue 2:

In the "GeoEvent Processor" web service, if you add an output to add new GIS feature, there is an option to "Delete Old Features". Even if you enable this, it will not delete the old features. The reason is, it performs a query like DATE_TIME < '[Some Date Time Value]'. For some reason this query does not contain the proper SQL Date Time query syntax and hence it fails to delete any features.

The only work around is to periodically delete the old features from the ArcGIS REST endpoint feature service url.

Hope these tips are helpful. If there are any new solutions, please add it in the comments section below.

Happy Holidays

Cheers
Adam

All Blogs so far ...