How to serialize List in VB.NET to JSON - asp.net

I have the following code to convert a list of messages into json :
Public Class MessageService
<OperationContract()> _
Public Function GetMessage(Id As Integer) As String
Dim msg As New Message()
Dim stream As New MemoryStream()
Dim serializer As New DataContractJsonSerializer(GetType(NewMessage))
Dim dtMessages = msg.getUnreadMessages("3A3458")
Dim list As New ArrayList
Dim m As New NewMessage()
m.Id = 1
m.Text = "mmsg"
list.Add(m)
list.Add(m)
serializer.WriteObject(stream, list)
stream.Position = 0
Dim streamReader As New StreamReader(stream)
Return streamReader.ReadToEnd()
End Function
End Class
But I got the following error :
The server was unable to process the request due to an internal error.
For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client,
or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.

Here:
Dim serializer As New DataContractJsonSerializer(GetType(NewMessage))
You indicate to the serializer that you want to serialize a NewMessage instance.
And here:
serializer.WriteObject(stream, list)
you are passing an Arraylist. This obviously is ambiguous. I would recommend you modifying your method so that it returns directly a strongly typed collection and leave the JSON serialization to the binding instead of writing plumbing code in your data contract:
Public Class MessageService
<OperationContract()> _
Public Function GetMessage(Id As Integer) As List(Of NewMessage)
Dim list As New List(Of NewMessage)
Dim m As New NewMessage()
m.Id = 1
m.Text = "mmsg"
list.Add(m)
Return list
End Function
End Class

Related

Consuming Webservice - Sending Signature- Error X509Certificate2 type was not expected

I'm consume an external webservice for sending data, using a web application in asp.net and Visual Studio 2010. The
sending of data must be digitally signed using a digital signature. The webservice contains the Signature class, where I
can fill all required values ​​(SignedInfo, SignatureValue, KeyInfo).
I'm trying to fill the KeyInfo structure with the certificate like this:
Dim Sig As New RSP.SignatureType
(...)
Sig.SignedInfo = Sig_info
(...)
Sig.SignatureValue = Sig_value
Dim rspKey_info As New RSP.KeyInfoType()
Dim rspX509 As New RSP.X509DataType()
Dim arrCertificate As X509Certificate2()
arrCertificate = myF.ReturnCertificateCC()
rspKey_info.ItemsElementName = New RSP.ItemsChoiceType2(0) {}
rspKey_info.ItemsElementName(0) = RSP.ItemsChoiceType2.X509Data
rspKey_info.Items = New Object(0) {}
rspX509.ItemsElementName = New RSP.ItemsChoiceType2(0) {}
rspX509.ItemsElementName(0) = RSP.ItemsChoiceType2.X509Data
rspX509.Items = New Object(0) {}
rspX509.Items(0) = arrCertificate (0)
Sig.KeyInfo = rspKey_info
xmlString = myF.SerializeAnObject(Sig)
When I try to serialize the Signature Object, an error occur:
"Error generating the XML document."
InnerException:
"{ " The System.Security.Cryptography.X509Certificates.X509Certificate2 type was not expected . Use XmlInclude or
SoapInclude attribute to specify types that are not known statically. "}"
Public Function SerializeAnObject(ByVal obj As Object) As String
Dim doc As System.Xml.XmlDocument = New XmlDocument()
Dim serializer As System.Xml.Serialization.XmlSerializer = New System.Xml.Serialization.XmlSerializer(obj.GetType())
Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream()
Try
serializer.Serialize(stream, obj)
stream.Position = 0
doc.Load(stream)
Return doc.InnerXml
Catch ex As Exception
Return ""
Finally
stream.Close()
stream.Dispose()
End Try
'#utilização
'dim xmlObject As string = SerializeAnObject(myClass)
End Function
Please help me...
I'm at several days trying to solve this...
Thanks in advance!
Regards!
rspX509.ItemsElementName = New RSP.ItemsChoiceType(0) {}
rspX509.ItemsElementName(0) = RSP.ItemsChoiceType.X509Certificate
rspX509.Items = New Object(0) {}
rspX509.Items(0) = arrCertificate (0)
rspKey_info.Items(0) = rspX509

Trying to return data from the asp.net web api

I'm trying to add the web api to an existing asp.net ASPX site.
All I want is for it to return (in JSON or XML) the results of my query - however I get the error: Unable to cast object of type 'System.Data.DataTable' to type 'System.Collections.Generic.IEnumerable`1[System.Web.UI.WebControls.Table]'.
... at the Finally part of the code.
My code in the API controller is:
Imports System.Web.Http
Imports System.Web
Imports System.Data
Imports System.Data.SqlClient
Public Class ValuesController
Inherits ApiController
' GET /api/<controller>
Public Function GetValues() As IEnumerable(Of Table)
Dim con As New SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=inv;Integrated Security=True")
Dim cmd As SqlCommand = New SqlCommand("select * from customers", con)
cmd.CommandType = CommandType.Text
Dim adapter As SqlDataAdapter = New SqlDataAdapter(cmd)
Dim dt As New DataTable
Using con
Try
con.Open()
adapter.Fill(dt)
'Check if any rows were returned
If dt.Rows.Count = 0 Then
'If no rows, return nothing
Return Nothing
Else
'Return the filled datatable
Return dt
End If
Catch ex As Exception
con.Close()
Throw ex
Finally
con.Close()
End Try
End Using
Return New String() {"value1", "value2"}
End Function
I think the answer is simply to change the signature of your function to As EnumerableRowCollection. When you take a DataTable object and use the AsEnumerable() method, it returns a collection of datarows as EnumerableRowCollection, although it is sufficient to just write it as EnumerableRowCollection.
Look at the exception message, it says that it cannot convert a DataRow collection to IEnumerable of System.Web.UI.WebControls.Table.
The problem is the signature of your function.
Public Function GetValues() As IEnumerable(Of Table)
It should be something like
Public Function GetValues() As IEnumerable(Of DataTable)

SQL Dataset to JSON

Alright I have been trying to figure this out and I read the MSDN page on the JavaScriptSerializer. However, I still can't figure out how to get this to work on an asp.net page. I want to convert my dataset into a json string so I can graph it using FLOT(graphing tool)
THIS MADE IT WORK THANKS FOR YOUR HELP GUYS: this is in vb.net for future people
Imports System.Web.Script.Serialization
....
Dim myObject = dataset.GetXml()
Dim jsonString = (New JavaScriptSerializer()).Serialize(myObject)
Reference the assembly System.Web.Extensions.dll and then do this:
using System.Web.Script.Serialization;
....
var myObject = ... your stuff ...
var jsonString = new JavaScriptSerializer().Serialize(myObject);
Check out the MSDN page for more info.
I did the following when I was working on a Project using PlotKit. I create a webservice to return the data and set the response format to Jason...this was while ago...should also work in 3.5
Here is a sample
<WebMethod()> _
<Script.Services.ScriptMethod(UseHttpGet:=True, ResponseFormat:=ResponseFormat.Json)> _
Public Function GetSales(ByVal a As String) As Generic.List(Of Sale)
Dim _conn As SqlConnection = New SqlConnection(connstr)
Dim _dr As SqlDataReader
Try
Dim _cmd As SqlCommand = New SqlCommand("select * from sales", _conn)
_conn.Open()
_dr = _cmd.ExecuteReader(CommandBehavior.CloseConnection)
If _dr.HasRows Then
Dim s As Sale
Dim c As New Generic.List(Of Sale)
While _dr.Read
s = New Sale
With s
.Month = _dr("monthname")
.TheSale = _dr("sale")
End With
c.Add(s)
End While
Return c
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
_conn.Close()
End Try
End Function
End Class
Here is the object class...notice I am serializing the object.
<Serializable()> _
Public Class Sale
Private _month As String
Private _sale As String
Public Property Month() As String
Get
Return _month
End Get
Set(ByVal value As String)
_month = value
End Set
End Property
Public Property TheSale() As String
Get
Return _sale
End Get
Set(ByVal value As String)
_sale = value
End Set
End Property
End Class
Check out the DataContractJsonSerializer, and this article on MSDN
public static string DStoJSON(DataSet ds)
{
StringBuilder json = new StringBuilder();
foreach (DataRow dr in ds.Tables[0].Rows)
{
json.Append("{");
int i = 0;
int colcount = dr.Table.Columns.Count;
foreach (DataColumn dc in dr.Table.Columns)
{
json.Append("\"");
json.Append(dc.ColumnName);
json.Append("\":\"");
json.Append(dr[dc]);
json.Append("\"");
i++;
if (i < colcount) json.Append(",");
}
json.Append("\"}");
json.Append(",");
}
return json.ToString();
}
Probably most useful to you is the dataset loop instead of the stringbuilder. You could loop these into an object, then use the javascript serializer library.
Or even better, if you are using asp.net mvc, you can just do this:
return Json(List<myobject>, JsonRequestBehavior.AllowGet);
but this way is quick & easy! -- I didn't quite test this! the appended comma might be wrong (or code can be improved) and the final row comma needs to be handled
I use the mvc way & never looked back :)

Scrambling URLS for dynamic data

What is the best method to obfuscate the urls created in Dynamic Data?
eg \Products\List.aspx?ProductId=2 could become
\Products\List.aspx?x=UHJvZHVjdElkPTI=
where "ProductId=2" is base 64 encoded to prevent casual snooping on
\Products\List.aspx?ProductId=3
\Products\List.aspx?ProductId=4
etc...?
I will probably have to inherit from an existing object and override some function
The question is which object and what function
GetActionPath of the Metamodel object seems interesting,
but how does the DynamicRoute "{table}/{Action}.aspx" play in into it...
Right now on Asp.net 1.1 site I use an custom implementation of the following code.
http://www.mvps.org/emorcillo/en/code/aspnet/qse.shtml It is HTTPModule that uses regular expression to rewrite all the querystrings and also with reflection changes the Querystring collection with decoded values.
So where is the hook to affect the change.
I have found the solution
With advice, I have implemented a Route that inherits from DynamicDataRoute.
The methods overridden were GetVirtualPath and GetRouteData.
Here is the global.asax page
routes.Add(New EncodedDynamicDataRoute("{table}/{action}.aspx") With { _
.Defaults = New RouteValueDictionary(New With {.Action = PageAction.List}), _
.Constraints = New RouteValueDictionary(New With {.Action "List|Details|Edit|Insert"}), _
.Model = model})
Here is the Encoded DynamicDataRoute.
Imports System.Web.DynamicData
Imports System.Web.Routing
''' <summary>
''' The purpose of this class to base 64 encode the querystring parameters.
''' It converts the keys to base64 encoded and back.
''' </summary>
Public Class EncodedDynamicDataRoute
Inherits DynamicDataRoute
Public Sub New(ByVal url As String)
MyBase.New(url)
End Sub
Public Overloads Overrides Function GetRouteData(ByVal httpContext As HttpContextBase) As RouteData
Dim routeData As RouteData = MyBase.GetRouteData(httpContext)
If Not (routeData Is Nothing) Then
DecodeRouteValues(routeData.Values)
End If
Return routeData
End Function
Private Sub EncodeRouteValues(ByVal routeValues As RouteValueDictionary)
Dim tableName As Object
If Not routeValues.TryGetValue("table", tableName) Then
Return
End If
Dim table As MetaTable
If Not Model.TryGetTable(DirectCast(tableName, String), table) Then
Return
End If
Dim strOutput As New StringBuilder
Dim val As Object
For Each column As MetaColumn In table.PrimaryKeyColumns
If routeValues.TryGetValue(column.Name, val) Then
strOutput.Append(column.Name & Chr(254) & val & Chr(255))
routeValues.Remove(column.Name)
End If
Next
Dim out As String = (Convert.ToBase64String(Encoding.ASCII.GetBytes(strOutput.ToString)))
If routeValues.ContainsKey("x") Then
routeValues.Item("x") = out
Else
routeValues.Add("x", out)
End If
End Sub
Public Overloads Overrides Function GetVirtualPath(ByVal requestContext As RequestContext, ByVal values As RouteValueDictionary) As VirtualPathData
EncodeRouteValues(values)
Return MyBase.GetVirtualPath(requestContext, values)
End Function
Private Sub DecodeRouteValues(ByVal routeValues As RouteValueDictionary)
Dim tableName As Object
If Not routeValues.TryGetValue("table", tableName) Then
Return
End If
Dim table As MetaTable
If Not Model.TryGetTable(DirectCast(tableName, String), table) Then
Return
End If
Dim enc As New System.Text.ASCIIEncoding()
Dim val As Object
If routeValues.TryGetValue("x", val) AndAlso val <> "AAA" Then
Dim strString As String = enc.GetString(Convert.FromBase64String((val)))
Dim nameValuePairs As String() = strString.Split(Chr(255))
Dim col As MetaColumn
For Each str11 In nameValuePairs
Dim vals() As String = str11.Split(Chr(254))
If table.TryGetColumn(vals(0), col) Then
routeValues.Add(val(0), col)
End If
Next
End If
End Sub
End Class
Here is how I did it:
I created 4 functions in a module:
public static string EncryptInt(int val)
public static int DecryptInt(string val)
public static string DecryptStr(string str)
public static string EncryptStr(string source)
When I wanted to create a url I did something like this:
string.Format(#"\path\file.aspx?ID={0}&name={1}",encrypt.EncryptInt(inID),encrypt.EncriptStr(inName));
When I wanted to get the results I would call the Decrypt function on retrieved param.
I used two types because it added a level of type safety to the system, but you could just use one with strings and then call int.Parse() as needed.
Does this answer your question?
For Microsoft's Dynamic Data I believe the hooks would be found in the code behind for the template pages.

Catching errors or exceptions

I built a mashup of google maps and weather.com and everytime one of these server is not responding my application hangs up too.What do you think I can do to prevent or minimize hanging up of my web apps?Hanging up like you can't navigate away from that page....
I got this code on my app code to access the weather service;
Public Class WeatherIn
Private _path As String
Private _cachedFile As String
Public Sub New(ByVal path As String)
_path = path
_cachedFile = String.Format("{0}\WeatherInCache.xml", _path)
End Sub
Public Function GetWeather(ByVal arg As String) As String
Return _getWebWeather(arg)
End Function
Private Function _getCachedWeather() As String
Dim str As String = String.Empty
Using reader As New StreamReader(_cachedFile)
str = reader.ReadToEnd()
End Using
Return str
End Function
Private Function _getWebWeather(ByVal arg As String) As String
Dim baseUrl As String = "http://xoap.weather.com/weather/local/{0}?cc=*&dayf=5&link=xoap&prod=xoap&par={1}&key={2}"
Dim jane As String = arg
Dim james As String = "api key"
Dim john As String = "another api key"
Dim url As String = String.Format(baseUrl, jane, james, john)
Using client As New WebClient()
Try
Dim xml As New XmlTextReader(client.OpenRead(url))
Dim xslt As New XslCompiledTransform()
xslt.Load(_path + "/Pathto.xslt")
Using writer As New StreamWriter(_cachedFile)
xslt.Transform(xml, Nothing, writer)
End Using
Return _getCachedWeather()
Catch exception As WebException
Dim xmlStr As String = "<errorDoc>"
xmlStr += "<alert>An Error Occurred!</alert>"
xmlStr += [String].Format("<message>{0}</message>", exception.Message)
xmlStr += "</errorDoc>"
Dim doc As New XmlDocument()
doc.LoadXml(xmlStr)
Dim reader As New XmlNodeReader(doc)
Dim xslt As New XslCompiledTransform()
xslt.Load(_path + "/Pathto.xslt")
Dim resultDocument As New XmlDocument()
Using writer As XmlWriter = resultDocument.CreateNavigator().AppendChild()
xslt.Transform(reader, DirectCast(Nothing, XsltArgumentList), writer)
End Using
Return resultDocument.OuterXml
End Try
End Using
End Function
Then I used the class above on my page where I display the weather like this:
'specific zip code or could be retrieved from querystring for dynamic retrieval
var jay="94576"
Dim weather As New WeatherIn(Server.MapPath(String.Empty))
Dim weatherData As String = weather.GetWeather(jay)
Response.ContentType = "text/xml"
Response.CacheControl = "no-cache"
Response.Write(weatherData)
which I retrieve the data and write on the page through javascript.Most of the time its the weather.com that goes down.I got no problem with google map its reliable....anybody got a solution why my page hangs up too if the remote server is not responding?The mashup is running smoothly if the remote server is responding...
When depending on external web services it is best to load asynchronously so that if one of them is slow you can show some kind of loading spinner to the page viewer. If it fails your page could simply report that reading from the web server failed and to try again later.
In this case I would load up the page with the Google map in place and then make an AJAX request for the Weather data.

Resources