Creating a cross domain web service - vb.net

So, I am very new to creating web services, but have successfully managed to make a simple webservice which returns information as I'd need from a database as List(Of dictionary(of string, string)) object.
For the purpose of testing, I have created this manually, my code looks like this:
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Web.Script.Serialization
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class test
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function dic() As String
Dim newDic As New List(Of Dictionary(Of String, String))
Dim one As New Dictionary(Of String, String)
one.Add("id", "1")
one.Add("name", "the name")
one.Add("price", "5.99")
newDic.Add(one)
Dim two As New Dictionary(Of String, String)
two.Add("id", "2")
two.Add("name", "item name two")
two.Add("price", "1299")
newDic.Add(two)
Dim s As New JavaScriptSerializer
Dim str As String = s.Serialize(newDic)
Return str
End Function
End Class
This webservice "dic" gives me serialized string/list looking like this:
[{"id":"1","name":"the name","price":"5.99"},{"id":"2","name":"item name two","price":"1299"}]
I can read this in VB code like this:
Sub loadMe() Handles Me.Load
Dim t As New websvce.testSoapClient
Dim d As String = t.dic
Dim s As New JavaScriptSerializer
Dim d2 = s.DeserializeObject(d)
Response.Write(d2(1)("name") & "<hr>")
End Sub
which gives me the output of the "name" element with index "1". It works fine.
However, unsurprisingly, it does not work when trying to grab this info with jQuery using code as follows:
$(document).ready(function () {
$.getJSON('URL/test.asmx/dic', function (data) {
alert(data);
});
});
So I have spent a good part of the day Googling this, and found all kinds of comments and conversations telling me about why cross domain scripting is not allowed and that there are ways round it using Proxies, adding headers to pages and so on... but... no conclusive solution to the problem.
Here's some of the SO questions I have found:
Origin http://localhost is not allowed by Access-Control-Allow-Origin
How to implement "Access-Control-Allow-Origin" header in asp.net
There's many more, but I cannot find an absolute solution, which fits my criteria. I want to output data in a format similar to that above, and access it from another domain with jQuery.
The easiest work around I have found is to write a handling page which runs on the receiving server, simply loading the data as per my VB code example above and operating as a webMethod on that server to spit out JSON, but I'd rather the whole thing could be handling by the web service, thus no need to run extra files on the consuming server.
EDIT; actually, I do also need to be able to perform POST operations.

Related

VB store list of records in a text file and read back

I have a VB program in VS2017. It reads many excel files and store relevant data in
Dim total_sessions As New List(Of Session_CSV_file)
The list is big (~10k), and includes about 20 fields each.
Is there a way in VB to store it in a file in one command and read it later on easily., without reading and writing each field?
Often I need to debug the later part. I prefer doing it without rerunning the whole first part.
Or is there a way in Visual Studio, to stop the run at a certain point, and store this point in a dump file, like simulators often do? (so they can run the simulation from this point later on)
Perhaps if you load your csv data into a DataTable instead:
Dim dt as New DataTable
dt.Columns.Add("Name")
dt.Columns.Add("Age", GetType(Int32))
For Each filepath in tenKFilePaths
For Each line in File.ReadAllLines(file)
Dim bits = line.Split(","c)
dt.Rows.Add(bits(0), Convert.ToInt32(bit(1))
Next line
Next filepath
Then you can save the whole lot to xml:
dt.WriteXml("c:\temp\my.xml")
Have a coffee, reboot etc the read them again and carry on where you left off:
Dim dt2 as New DataTable
dt2.ReadXml("c:\temp\my.xml")
Raw datatables are a bit difficult to work with because you end up accessing their rows and column data by string indexing and having to cast it a lot - fairly lame. There is a better way to use them, as visual studio can create custom classes that inherit from the base datatables and offer lots of functionality that does away with all the awkwardness of dealing with datatables as a very generic thing. Just like the forms designer creates a UI form that inherits from Form, the dataset designer creates custom datatables that inherit from the base
If you add a new DataSet type object to your project, double click it it opens something like a database designer. Right click that surface and choose Add DataTable, Add your Columns with their respective datatypes etc - this is the equivalent of your Session_Csv_File class, with its properties and fields. Double click on it and you can add code etc - if your session_csv_file has custom methods you can transfer their code to the custom data row
Imagine I created a new datatable in a DataSet and called it SessionCsvFiles. Imagine I added a Name and Age column, and I added a custom method called BlahBlah
I'd then be able to say in code things like:
Dim dt as New MyCustomDataSet.SessionCsvFilesDataTable
'it's like making a new SessionCsvFile
Dim r = dt.NewSessionCsvFilesRow()
'It's like setting your properties
r.Name = csvBits(0)
r.Age = Convert.ToInt32(csvBits(1))
'It's like adding your file to the List
dt.Add(r)
You now have virtually the same thing as you had before - a collection of objects that represents things about your csv files. The difference is with this route it has an already-built-in way of saving all the properties and the collection to xml and reading it back again
Add the Serializable attribute to the Class. I added a parameterized constructor for ease in building my list but you must provide a constructor without parameters for this to work. Thus, the empty Sub New.
<Serializable()>
Public Class Session_CSV_file
Public Property ID As Integer
Public Property Name As String
Public Property Type As String
Public Sub New()
End Sub
Public Sub New(SessID As Integer, SessName As String, SessType As String)
ID = SessID
Name = SessName
Type = SessType
End Sub
End Class
The add Imports System.Xml.Serialization to the top of the file.
Private Sub SaveList()
Dim serializer = New XmlSerializer(GetType(List(Of Session_CSV_file)))
Using writer As New StreamWriter("C:\Users\xxx\Documents\XMLtest.xml")
serializer.Serialize(writer, lst)
End Using
End Sub
I filled my list as follows but you can fill you list any way you choose.
Private lst As New List(Of Session_CSV_file)
Private Sub FillList()
Using cn As New SqlConnection(My.Settings.CoffeeConnection),
cmd As New SqlCommand("Select Top 10 * From Coffees;", cn)
cn.Open()
Dim reader = cmd.ExecuteReader
While reader.Read
Dim sess As New Session_CSV_file(reader.GetInt32(0), reader.GetString(1), reader.GetString(3))
lst.Add(sess)
End While
End Using
End Sub
To recreate the list... (OOps! forgot this)
Private RehydratedList As New List(Of Session_CSV_file)
Private Sub CreateListFromXML()
Dim serial As New XmlSerializer(GetType(List(Of Session_CSV_file)))
Using fs As New FileStream("C:\Users\maryo\Documents\XMLtest.xml", FileMode.Open)
RehydratedList = DirectCast(serial.Deserialize(fs), List(Of Session_CSV_file))
End Using
For Each item In RehydratedList
Debug.Print(item.ToString)
Next
End Sub

Dictionary comes back from cache as Null/Nothing

I'm writing some vb.net code to retrieve some data from middleware, do some stuff with it, and then save a dictionary of name/value pairs to cache for quick retrieval when needed.
It all seems to go well until I retrieve the object from cache and it is always Null/Nothing.
Yet in the watch window I can see my cached object and it has data in it.
Thinking maybe it's a serialization issue I made a new class that inherits Dictionary and is marked as serializable but I still get the same results.
So right now I have this class:
<Serializable()> Public Class SerialDict
Inherits Dictionary(Of String, String)
Public Sub New()
End Sub
End Class
I populate it and put it into cache like this:
Dim Licenses As New SerialDict
For Each r As DataRow In dtLicenses.Rows
Dim prikey As String = r("SettingID").ToString.Trim
Dim decryptionKey As String = GetHash((xx))
Dim licData As String = DecryptData(r("SettingVal"), decryptionKey)
Licenses.Add(r("SettingKey"), licData)
Next
If IsNothing(HttpContext.Current.Cache("Licenses")) Then
HttpContext.Current.Cache.Add("Licences", Licenses, Nothing, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, Nothing)
End If
Then elsewhere we need to check that data so I try to retrieve it like this:
Dim Licences As SerialDict = CType(HttpContext.Current.Cache("Licenses"), SerialDict)
At this point Licenses is always Nothing, but the watch window shows data in HttpContext.Current.Cache("Licenses").
Any suggestions? Thanks!

Get IP From Google

I'm writing an app in vb.net that needs public IP address in text only format. I'd knew there is lots of site that give you your IP in text format. But where is always a chance of being closed or getting out of service. But the Google will not ever stop! Now I want to get my ip from google searching. For example if you search "my ip" in google it will bring your ip like this:
Sample of search
Is anyway to get IP from Google?
Thanks guys but I found a way:
At first import some namespaces:
Imports System.Net
Imports System.Text.RegularExpressions
Now lets write a function:
Dim client As New WebClient
Dim To_Match As String = "<div class=""_h4c _rGd vk_h"">(.*)"
Dim recived As String = client.DownloadString("https://www.google.com/search?sclient=psy-ab&site=&source=hp&btnG=Search&q=my+ip")
Dim m As Match = Regex.Match(recived, To_Match)
Dim text_with_divs As String = m.Groups(1).Value
Dim finalize As String() = text_with_divs.Split("<")
Return finalize(0)
It's now working and live!
Hard-coded Div Class names make me a bit nervous because they can easily change at any time, so, I expanded on Hirod Behnam's example a little bit.
I removed the Div Class pattern, replacing it with a simpler IP address search, and it'll return only the first one found, which for this search, should be the first one shown on the page (your external IP).
That also removed the need for splitting the results into the array, and those related vars. I also simplified the Google search string to the bare minimum.
It'd still probably be a nice touch to include a timeout or two for the .DownloadString() and the .Match() respectively, if speed is of the essence.
Private Function GetExternalIP() As String
Dim m As Match = Match.Empty
Try
Dim wClient As New System.Net.WebClient
Dim strURL As String = wClient.DownloadString("https://www.google.com/search?q=my+ip")
Dim strPattern As String = "\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b"
' Look for the IP
m = Regex.Match(strURL, strPattern)
Catch ex As Exception
Debug.WriteLine(String.Format("GetExternalIP Error: {0}", ex.Message))
End Try
' Failed getting the IP
If m.Success = False Then Return "IP: N/A"
' Got the IP
Return m.value
End Function

Setting DirectShow VSFilter file name through code

I've been searching for a way to do this using VB.NET and DirectShowNET for many months. Thanks to the question Is there any way to control DirectShow VSFilter programmatically? asked last week, I'm on the right track but need help getting over the final hurdle.
As per the answer to the above question, I can get hold of the filter's interface and call put_FileName(). However, when I check the filter in the running graph, the file name is either junk or blank. Here's how I load the filter:
Dim clsidVobsub As New Guid("{93A22E7A-5091-45EF-BA61-6DA26156A5D0}")
Dim filterVobsub As IBaseFilter
Dim type__2 As Type = Type.GetTypeFromCLSID(clsidVobsub)
filterVobsub = DirectCast(Activator.CreateInstance(type__2), IBaseFilter)
Graph.AddFilter(filterVobsub, "My VobSub")
Dim vobSettings As ISettingsInterface = DirectCast(filterVobsub, ISettingsInterface)
Dim fn As String = "C:\Leta\testing.srt"
Dim hr as Integer = vobSettings.put_FileName(fn)
That seems to work as it should, so I think the problem lies with the way I'm trying to marshall the function call in the interface definition.
<PreserveSig()> _
Function put_FileName(<MarshalAs(UnmanagedType.LPWStr)> fn As String) As Integer
Can anybody see what I'm doing wrong?
EDIT: The ISettingsInterface is my own. It's declared like this:
<ComImport(), System.Security.SuppressUnmanagedCodeSecurity(), Guid("EBE1FB08-3957-47ca-AF13-5827E5442E56"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface ISettingsInterface
<PreserveSig()> _
Function get_FileName(<MarshalAs(UnmanagedType.LPWStr)> fn As String) As Integer
<PreserveSig()> _
Function put_FileName(<MarshalAs(UnmanagedType.LPWStr)> fn As String) As Integer
End Interface
SOLUTION: It was actually already working! I was running a test project and hadn't bothered rendering the video branch. I mistakenly thought VSFilter would display the file name as it does when it picks up an SRT with the same name as the video. Apparently it doesn't when you set the file name through the interface. So instead of checking the filter's property page in my graph in GraphEdit, I should simply have rendered the video and I'd have seen the subtitles in the video window.

Linq OData REST API to Query a SharePoint List

Hey all I am new at using linq and found a good example here. However, its all in C# and when trying to convert it I get a lot of errors that I can not seem to fix.
Imports System.Linq
Imports HelperApp.SPTrackerData
Imports System.Net
Public Class frm_tasks
Private Sub cmdCheck_Click(sender As Object, e As EventArgs) Handles cmdCheckMail.Click
Dim dc As New TeamSiteDataContext(New Uri("http://intranet/_vti_bin/listdata.svc"))
dc.Credentials = CredentialCache.DefaultNetworkCredentials
Dim result = From d In dc.Inventory With { _
Key.Title = d.Title, _
Key.Description = d.Description, _
Key.Cost = d.Cost _
}
For Each d As var In result
Console.WriteLine(d)
Next
End Sub
End Class
I connected my SharePoint to a Service Reference called SPTrackerData as it stated on the website but I can not seem to fix the following:
TeamSiteDataContext: I'm not sure where this is in the original code
so I really have no idea on where or what to replace it with in my code above.
The Linq part: (Dim result =...) I tried my best to form it as i thought it needed to look like but its all wrong.
The one thing that doesn't make since to me is why did I create a service reference and not even use it at all within that code???
TeamSiteDataContext represents the runtime context of the data service.
When you add a reference to an OData-based service (listdata.svc) using Add Service Reference dialog in Visual Studio, a representation of TeamSiteDataContext entity container class that inherits from DataServiceContext is being generated.
Below is provided the converted to VB.Net example:
Sub Main()
Dim dc As New TeamSiteDataContext(New Uri("http://intranet/_vti_bin/listdata.svc"))
dc.Credentials = CredentialCache.DefaultNetworkCredentials
Dim result = From d In dc.Inventory Select New With { _
Key .Title = d.Title, _
Key .Description = d.Description, _
Key .Cost = d.Cost _
}
For Each d In result
Console.WriteLine(d)
Next
End Sub
References
Generating the Data Service Client Library (WCF Data Services)