2

I have an update panel. The contents of which contain a Google Map and a multiline text box in which users can paste Postal Codes. The Postal Codes are taken and used in a WHERE IN (list) mysql statement to return the latitude and longitude from our database. Once the Dataset is complete it is turning into a JSON string for create map markers.

The update panel is causing issues so though I would remove it, however in doing so the Dataset only gets the last record from the last entry in the list and the JSON data equally only contain the last entry.

Here is my asps code:-

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
    <table border="0px" style="width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: small; color: #000000;">
        <tr>
        <td class="style15" valign="top">
            <table border="0px" style="border: 1px solid #000000; font-family: Arial, Helvetica, sans-serif; font-size: small; color: #000000;"width="100%">
                <tr>
                    <td align="center" class="style14" colspan="2">
                        <asp:TextBox ID="PostcodeListTextBox" runat="server" Height="500px" 
                            Width="240px" TextMode="MultiLine"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td align="center" class="style14" colspan="2">
                        <asp:Button ID="ShowLocsButton" runat="server" Text="Show Locations" />
                    </td>
                </tr>
             </table>
        </td>

         <td align="center" valign="top">
                <div id="mapArea" style="border:1px solid black">
                </div>
                <asp:Literal ID="Literal1" runat="server"></asp:Literal>
            </td>
        </tr>
        </table>
 </ContentTemplate>
</asp:UpdatePanel>

And here is my code behind:-

Imports MySql.Data.MySqlClient
Imports MySql.Data
Imports System.Data
Imports System.Web
Imports System.IO
Imports System.Configuration
Imports System.Web.Script.Services
Imports System.Web.Script.Serialization
Partial Class admin_routing
Inherits System.Web.UI.Page
Dim i As Integer = 0
Dim markers As String = ""

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub

Protected Sub ShowLocsButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ShowLocsButton.Click
    Dim ConnString As String = ConfigurationManager.ConnectionStrings("ConnString").ConnectionString
    Dim conn As New MySqlConnection(ConnString)
    Dim command As New MySqlCommand
    Dim ds As New DataSet
    Dim sql As String
    Dim dt As New DataTable
    Dim markers As String = ""
    Dim i As Integer = 0
    Dim PCList As String = Replace(Me.PostcodeListTextBox.Text, vbLf, "','")
    Dim da As New MySqlDataAdapter
    Dim myJS As New StringBuilder
    PCList = "'" & PCList & "'"
    sql = "SELECT postcode, latitude,longitude FROM geocodes WHERE postcode IN (" & PCList & ")"
    da = New MySqlDataAdapter(sql, conn)
    da.Fill(ds, "locations")
    Dim jsonData = GetJson(ds.Tables(0))
    'Dim jsondata = DataSetToJSON(ds)
    'Me.JsonTextBox.Text = jsonData
    myJS.AppendLine("<script type=""text/javascript"">" & vbCrLf)
    myJS.AppendLine("var mapOptions = {center: new google.maps.LatLng(54.236107, -4.548055999999974)," & vbCrLf)
    myJS.AppendLine("zoom: 6," & vbCrLf)
    myJS.AppendLine("mapTypeId : google.maps.MapTypeId.ROADMAP" + "};" & vbCrLf)
    myJS.AppendLine("var myMap = new google.maps.Map(document.getElementById('mapArea'), mapOptions);" & vbCrLf)
    myJS.AppendLine("var markers = JSON.parse(""<%=jsonData %>"");" & vbCrLf)
    myJS.AppendLine("console.log(""<%=jsonData %>"");" & vbCrLf)
    myJS.AppendLine("for (i = 0; i < markers.length; i++) {" & vbCrLf)
    myJS.AppendLine("var data = markers[i];" & vbCrLf)
    myJS.AppendLine("var myLatLng = new google.maps.LatLng(data.latitude, data.longitude);" & vbCrLf)
    myJS.AppendLine("var marker = new google.maps.Marker({" & vbCrLf)
    myJS.AppendLine("position: myLatLng," & vbCrLf)
    myJS.AppendLine("map: myMap," & vbCrLf)
    myJS.AppendLine("title:  data.postcode" & vbCrLf)
    myJS.AppendLine("});" & vbCrLf)
    myJS.AppendLine("}" & vbCrLf)
    myJS.AppendLine("</script>")
    Dim str As String = myJS.ToString
    ScriptManager.RegisterStartupScript(Me, Me.GetType(), "Init", myJS.ToString, True)
End Sub
Public Shared Function GetJson(ByVal dt As DataTable) As String
    Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer()
    Dim rows As New System.Collections.Generic.List(Of System.Collections.Generic.Dictionary(Of String, Object))()
    Dim row As System.Collections.Generic.Dictionary(Of String, Object) = Nothing
    For Each dr As DataRow In dt.Rows
        row = New System.Collections.Generic.Dictionary(Of String, Object)()
        For Each col As DataColumn In dt.Columns
            row.Add(col.ColumnName, dr(col))
        Next
        rows.Add(row)
    Next
    Return serializer.Serialize(rows)
End Function

End Class

Also I'm having trouble passing the JSON to the javascript.

Frank Nicklin
  • 105
  • 10

1 Answers1

0

I know this can be done using WebMethods. I hope this isn't too far from what you are looking for.

HTML:

<table border="0px" style="width: 100%; font-family: Arial, Helvetica, sans-serif; font-size: small; color: #000000;">
    <tr>
    <td class="style15" valign="top">
        <table border="0px" style="border: 1px solid #000000; font-family: Arial, Helvetica, sans-serif; font-size: small; color: #000000;"width="100%">
            <tr>
                <td align="center" class="style14" colspan="2">
                    <textarea ID="PostcodeListTextBox" cols="40" rows="5"></textarea>
                </td>
            </tr>
            <tr>
                <td align="center" class="style14" colspan="2">
                    <button type="button" ID="ShowLocsButton" onclick="GetPostalJSON()">Show Locations</button>
                </td>
            </tr>
         </table>
    </td>

     <td align="center" valign="top">
            <div id="mapArea" style="border:1px solid black"></div>
        </td>
    </tr>
</table>

There isn't really any need for you to use server side controls at least for what you explained. Though if you do want to use them, I think you need to prefix your selector. ex. #MainContent_PostcodeListTextBox.

VB.NET

To use WebMethods you will need to add Imports System.Web.Services to your imports.

Imports MySql.Data.MySqlClient
Imports MySql.Data
Imports System.Data
Imports System.Web
Imports System.Web.Services
Imports System.IO
Imports System.Configuration
Imports System.Web.Script.Services
Imports System.Web.Script.Serialization

Partial Class admin_routing
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub


<WebMethod()>
Public Shared Function GetJson(PCList as String) As String

    Dim ConnString As String = ConfigurationManager.ConnectionStrings("ConnString").ConnectionString,
        conn As New MySqlConnection(ConnString),
        da As New MySqlDataAdapter,
        ds As New DataSet,
        sql = "SELECT postcode, latitude,longitude FROM geocodes WHERE postcode IN (" & PCList & ")"

    da = New MySqlDataAdapter(sql, conn)
    da.Fill(ds, "locations")
    Dim dt as DataTable = ds.Tables(0)

    Dim rows As New System.Collections.Generic.List(Of System.Collections.Generic.Dictionary(Of String, Object))(),
        row As System.Collections.Generic.Dictionary(Of String, Object) = Nothing

    For Each dr As DataRow In dt.Rows
        row = New System.Collections.Generic.Dictionary(Of String, Object)()
        For Each col As DataColumn In dt.Columns
            row.Add(col.ColumnName, dr(col))
        Next
        rows.Add(row)
    Next

    Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer()
    Return serializer.Serialize(rows)
End Function

I removed any unnecessary code and I moved the code that is used to build up your DataTable into the GetJson function, but aside from that it is the same as you had it. If you notice anything missing (like where you build up your postal code string you use in your where in) it is done in the JS. See below.

Javascript:

<script type="text/javascript">
    var myMap;

    function GetPostalJSON(){
        var res = $("#PostcodeListTextBox").val().split("\n"),
            postCodeStr = "";

        for (var i = 0; i < res.length; i++) {
            if (i > 0) {
                postCodeStr += ","
            }
            postCodeStr += "'" + res[i].trimRight() + "'"
        }

        PageMethods.GetJson(postCodeStr, function(result){
            UpdateMarkers(result)
        }); 
    }

    function CreateMap(){
        var mapOptions = {
                            center: new google.maps.LatLng(54.236107, -4.548055999999974),
                            zoom: 6,
                            mapTypeId : google.maps.MapTypeId.ROADMAP
                        };

        myMap = new google.maps.Map(document.getElementById('mapArea'), mapOptions);
    }

    function UpdateMarkers(jsonData){
        if (myMap == null) CreateMap()

        var markers = JSON.parse(jsonData);
        console.log(jsonData);
        for(i =0; i < markers.length; i++) {
            var data = marker[i];
            var myLatLng = new google.maps.LatLng(data.latitude, data.longitude);
            var marker = new google.maps.Marker({
                position: myLatLng,
                map: myMap,
                title:  data.postcode
            });
        }
    }

</script>

Basically any JS you were building up with your StringBuilder I would just put on the front end. It seems like a waste to create a map every time someone presses the button, so you might as well make that global and check to see if it has been created before modifying it. Something that you may not recognize is the PageMethods.GetJson part. That calls the WebMethod.

Jeshicat
  • 103
  • 6
  • Thanks for the code, will have to test out tomorrow, just one question, where is #txtA taken from in the Javascript. – Frank Nicklin Nov 02 '16 at 19:22
  • Woops that is supposed to be #PostcodeListTextBox. I forgot to update it when I was testing out that bit. I updated the code :) – Jeshicat Nov 03 '16 at 01:15
  • I'm getting an error GetPostalJSON() is not a member of... I have pasted the Javascript code at the bottom of the aspx page. – Frank Nicklin Nov 03 '16 at 10:21
  • OK, changed onClick to OnClientClick solved that, but getting an error here JavaScript runtime error: '$' is undefined at var res = $("#PostcodeListTextBox").val().split("\n"), – Frank Nicklin Nov 03 '16 at 10:24
  • I have added jquery to my app, but getting this error JavaScript runtime error: Unable to get property 'split' of undefined or null reference – Frank Nicklin Nov 03 '16 at 11:12
  • I have added jquery to my app, but getting this error JavaScript runtime error: Unable to get property 'split' of undefined or null reference. As a check window.alert($("#PostcodeListTextBox").val()) returns undefined. – Frank Nicklin Nov 03 '16 at 11:21
  • If you left your control an ASP Control then you will need to use $("#MainContent_PostcodeListTextBox").val() – Jeshicat Nov 03 '16 at 11:57
  • OK, I am getting the value by using this var el = document.getElementById("<%=PostcodeListTextBox.ClientID%>").value; var res = el.split("\n"), but I am getting an error JavaScript runtime error: 'PageMethods' is undefined. I have added _ under _ but still getting error. – Frank Nicklin Nov 03 '16 at 12:04
  • I believe you need to add a ScriptManager somewhere on the page or in your Master Page if you have one. I have this in my code: – Jeshicat Nov 03 '16 at 12:07
  • OK, I have standard ScriptManager, I'll change to the Ajax version. – Frank Nicklin Nov 03 '16 at 12:23
  • AjaxScriptManager made no difference, still getting the PageMethods undefined error. I have checked and EnablePageMethods is set to True – Frank Nicklin Nov 03 '16 at 12:30
  • http://stackoverflow.com/questions/18242334/pagemethods-is-not-defined-in-aspx-page do any of these solutions help? Can you call the WebMethod with an ajax call? – Jeshicat Nov 03 '16 at 13:02
  • I don't think you need to use the Ajax version. You could probably use the normal ScriptManager. I was just reading and I think there might be something we need to add to the web.config. – Jeshicat Nov 03 '16 at 13:08
  • Take a look at the accepted answer in this: https://forums.asp.net/t/1886251.aspx?Microsoft+JScript+runtime+error+PageMethods+is+undefined it shows a working example. Make sure the ScriptManager is placed above the javascript you added. – Jeshicat Nov 03 '16 at 13:14
  • I ve got the web methods working now by making the web method function a shared (static) function, this got rid of the error, however, the json list of geo locations is not being picked by by the Javascript, everything else seems OK. – Frank Nicklin Nov 03 '16 at 20:41
  • Ah yes, I thought in your original code it was already Shared so I didn't mention that. What does it print out when you do console.log(result) in the dev tools? Usually F12 will pop open the dev tools. I like Chromes the best. – Jeshicat Nov 04 '16 at 12:30