WCF Error - An error occurred while receiving the HTTP response to http://localhost:50750/*******.svc - vb.net

I am receiving the following error while debugging.
An error occurred while receiving the HTTP response to http://localhost:50750/FIGService.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Now I have seen many posts where people have had that error, I have cut my WCF down to absolute barebones and I am still getting the error, I am running the following:
Public Function TestXML(ByVal Username As String, ByVal Password As String, ByVal XML As String) As XmlDocument Implements FreshCloud.TestXML
Dim ReturnXMLDoc As New XmlDocument()
If ValidateLogin(Username, Password) <> False Then
ReturnString = "<FreshLead><Result><Message>Failed - XSD Validation</Message><DateTime>" & Date.Now.ToString & "</DateTime></Result></FreshLead>"
ReturnXMLDoc.LoadXml(ReturnString)
Return ReturnXMLDoc
End If
End Function
Don't worry about the uselessness of the code I literally just copy and pasted various bits to run a test, this is than ran with a simple test app with a button:
Dim client As FreshCloudClient = New FreshCloudClient()
Dim strXML = client.TestXML("ABC", "BS", "Doesn't Matter")
Dim strTest = strXML
client.Close()
I receive the error just returning the above, please any light that can be shed would be grateful this is a big project that I have had to sink my teeth into a Microsoft's vague error messages do not help a learner.
Cheers! :)
UPDATE
After digging through the logs for WCF I stumbled across this:
Type 'System.Xml.XmlDocument' is an invalid collection type since it does not have a valid Add method with parameter of type 'System.Object'.
Can anyone share with me why this exception would be thrown up by WCF?
Cheers.
UPDATE 2
OK so following Lerners advice I have now got the following:
Public Function TestXML(ByVal Username As String, ByVal Password As String, ByVal XML As String) As XElement Implements FreshCloud.TestXML
Dim ReturnXMLDoc
If ValidateLogin(Username, Password) <> False Then
ReturnString = "<FreshLead><Result><Message>Failed - XSD Validation</Message><DateTime>" & Date.Now.ToString & "</DateTime></Result></FreshLead>"
ReturnXMLDoc = XElement.Parse(ReturnString)
Return ReturnXMLDoc
End If
End Function
On my client side of have said to put the response to a variable and Console.WriteLine the variable and it just returned System.Object?
Surely this should return the XML as it shows in ReturnXMLDoc variable when I debug on the WCF side of things?
UPDATE 3
WORKING!
Lerner put me in the right ballpark and I just had to update the Service Definitions from within my 'Client' Application.
Cheers.

Return XElement instead of XDocument, XElement is IXmlSerializable.
var xml = XElement.Parse(ReturnString);
return xml;

Related

VB.net POST method using HTTPclient

Hello I am trying to access a webform with data. However my code does not have error but its not working. It is supposed to send me a text message using the Web API provided by the telco carrier. Any assistance and advise will be greatly appreciated.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim client As New HttpClient
Dim url = $"some url"
Dim data2 = "{""username"": ""someuname"", ""password"":""somepass"", ""msisdn:""some number"", ""content:""Hello, this is a sample broadcast"", ""shortcode_mask:""somemask""}"
Dim payload = Newtonsoft.Json.JsonConvert.SerializeObject(data2)
Dim buffer = Encoding.UTF8.GetBytes(payload)
Dim bytes = New Net.Http.ByteArrayContent(buffer)
bytes.Headers.ContentType = New Net.Http.Headers.MediaTypeHeaderValue("application/json")
Dim request = client.PostAsync(url, bytes)
Catch Ex As Exception
Console.WriteLine()
End Try
End Sub
End Class
There are a few issues in your code. Let me start with the most important one first:
Catch Ex As Exception
Console.WriteLine()
End Try
This code means: If an error occurs, throw away all useful information about the error that could help me find the cause, then write an empty line to the console and pretend nothing bad happened.
Don't do that. Remove the whole try-catch block, then re-run your code again. If you get an exception: That's great, because .NET is now telling you what is wrong with your code! If you understand the error message, use it to fix your code. If you don't understand it, feel free to ask the community on StackOverflow.
Second issue:
This line
Dim request = client.PostAsync(url, bytes)
starts an asynchronous web request. You don't wait for the result, so you don't know whether it succeeded or not.
You're supposed to Await async methods, but if you aren't familiar with the async/await pattern yet, I won't be able to give you all the necessary background in the single StackOverflow answer. Until you have familiarized youself with async/await, you can synchronously wait for the result by accessing the Result property of the Task that has been returned:
Dim response = client.PostAsync(url, bytes).Result
response.EnsureSuccessStatusCode()
Third issue: You JSON-serialize something which is already JSON. If your data is already JSON, just use it as the payload without calling SerializeObject.
Your data2 is a string. When you use the JSON library to serialize it, it probably isn't in the JSON structure that your URL endpoint expects. Create a Type, fill it with data, and pass that to your JsonCoverter
Thank you Heinzi, here is the final working code based on your concepts:
Public Class Form1
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim client As New HttpClient
Dim url = $"some url"
Dim data2 = "
{""username"": ""some uname"", ""password"": ""somepass"", ""msisdn"": ""somenumber"", ""content"": ""Hello, this is a sample broadcast"", ""shortcode_mask"" :""somemask""}"
Dim buffer = Encoding.UTF8.GetBytes(data2)
Dim bytes = New ByteArrayContent(buffer)
bytes.Headers.ContentType = New Headers.MediaTypeHeaderValue("application/json")
Dim request1 = Await client.PostAsync(url, bytes)
Dim response = client.PostAsync(url, bytes).Result
response.EnsureSuccessStatusCode()
End Sub
End Class
I can now receive text messages :)

Getting "The underlying connection was closed: An unexpected error occurred on a send" on GetReponse() but not via browser

I am attempting to utilize a REST service that uses a GET method. I'm using the .Net Framework 4.5.2. What I've written below is just a test to see if I can actually make the request. If I put the URL directly into a browser I get a good response back with string data in json format. But when I attempt to run the code I end up getting the following error back:
"The underlying connection was closed: An unexpected error occurred on a send."
InnerException = {"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."}
I have tried setting the keepalive to both true and false and I've tried using a WebClient along with DownloadString too....all result in the same error. Does anyone have any idea of what I'm missing? Or is this a problem somehow on the server side?
Dim script As String = "236"
Dim deploy As String = "1"
Dim compid As String = "915960_SB2"
Dim h As String = "value1"
Dim id As String = "1241389"
Dim status As String = "in freezer"
Dim request As HttpWebRequest
Dim response As HttpWebResponse
Try
'I have removed the real website name from this code.
Dim theurl As String = "https://website/app/site/hosting/scriptlet.nl?script={0}&deploy={1}&compid={2}&h={3}&Id={4}&Status={5}"
Dim url As String = String.Format(theurl, script, deploy, compid, h, id, status)
request = HttpWebRequest.Create(url)
request.Method = "GET"
request.ContentType = "application/json"
'This is where the error occurs
response = request.GetResponse()
Catch ex As Exception
Dim test as string=""
Finally
End Try
I solved it. I stumbled upon the following web site where someone else had been having the same issue.
http://www.avivroth.com/2013/05/02/rest-calls-in-net-c-over-ssl-https/
The solution is to set the security protocol. I just went down the list from ssl to tls11 then to tls12 and found that the last one worked.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

DocuSign SOAP API Update (Correct) Envelope Expiration

I'm using vb.net (4.0) to interact with the DocuSign API. I'm trying to make a process that allows a user to add 30 days to the current expiration date instead of logging into DocuSign.net to correct the envelope. The code seems to work fine (doesn't throw any errors) but the correction doesn't happen on DocuSign's side.
Me.EnvelopeID is the Envelope's ID
DocuService is the namespace of the DocuSign API Service Reference.
Me.AuthorizationString is the Username, Password, Account# and Integrator Key to send as HTTP headers.
Private Sub UpdateExpiration()
'Get envelope details
Dim orig As DocuService.Envelope = ExecuteSoap(Function(client) client.RequestEnvelope(Me.EnvelopeID, False), Me.AuthorizationString)
Dim cor As New DocuService.Correction
cor.EnvelopeID = Me.EnvelopeID
cor.Reminders = orig.Notification.Reminders
cor.Expirations = orig.Notification.Expirations
cor.Expirations.ExpireAfter = (Integer.Parse(orig.Notification.Expirations.ExpireAfter) + 30)
'Execute Correction
Dim cord As DocuService.CorrectionStatus = Me.ExecuteSoap(Function(client) client.CorrectAndResendEnvelope(cor), Me.AuthorizationString)
'If I add a break point on the next line and check the values of cord,
'there is a returned CorrectionStatus object but every property in the object is "Nothing"
Dim check As DocuService.Envelope = ExecuteSoap(Function(client) client.RequestEnvelope(Me.EnvelopeID, False), Me.AuthorizationString)
Console.WriteLine(check.Notification.Expirations.ExpireAfter & " " & (Integer.Parse(orig.Notification.Expirations.ExpireAfter) + 30))
If check.Notification.Expirations.ExpireAfter = (Integer.Parse(orig.Notification.Expirations.ExpireAfter)) Then
'Success :)
MsgBox("success!")
Else
'Failure :(
MsgBox("failure!")
End If
End Sub
Private Function ExecuteSoap(Of TResult)(func As Func(Of DSAPIServiceSoapClient, TResult), authorizationString As String) As TResult
Using client As New DocuService.DSAPIServiceSoapClient(My.Settings.DocusignMode)
Using scope As OperationContextScope = New System.ServiceModel.OperationContextScope(client.InnerChannel)
Dim hp As HttpRequestMessageProperty = New HttpRequestMessageProperty
hp.Headers.Add("X-Docusign-Authentication", authorizationString)
OperationContext.Current.OutgoingMessageProperties(HttpRequestMessageProperty.Name) = hp
Return If(func IsNot Nothing, func(client), Nothing)
End Using
End Using
End Function
We use the same ExecuteSOAP function and AuthorizationString to create & send envelops, and do recipient updates so I know these are correct. I'm not sure whats wrong!
This is most likely 1 of 3 possibilities.
I'm surprised its not error-ing out, but you should not be putting your accountId in the http auth header. See page 19 the SOAP PDF guide:
http://www.docusign.com/sites/default/files/DocuSignAPI_Guide.pdf
There is something else not configured correctly with your SOAP API call. Inspect your raw outgoing request and ensure the xml is what you expect. Post the raw request here if not sure.
A bug with DocuSign. First rule out the other two options and if no dice still post a comment here and I can get a bug logged on DocuSign's side. Also a good test would be to make the correction call through the REST api to see if you can get that to work.

Issue in For-Each Loop with DataTable.Rows inside Web Service [vb.net]

I have the following For Each loop inside of a web method that is part of a web service. It is meant to put all of the State names into one string so I can parse it out inside of an ajax control:
<WebMethod()> Public Function getState(ByVal country As String) As String
Dim oresult As New DataTableResults
Dim oData As New Location(_connstr)
oresult = oData.getState(country)
Dim states As String = ""
For Each row As DataRow In oresult.dtData.Rows
states = states & row.Item("StateText") & ","
Next
Return states
End Function
I tried stepping through it and it adds all of the items to the string, but an issue comes up when it exits the loop. It is then that it just shows that the webpage cannot be displayed and doesn't give any sort of error message other than 'HTTP 500 Internal Server Error.
Thanks

Accessing Files On Server By Specifying Credentials

Our company has a share point document server where the UNC looks something like this: \\theserver.ourdomain.com\rootdirectory
Currently this drive is mapped to the Z:\ on my local computer. To access the Z:\ you have to specify (each time you login) credentials (in our case is it our username and password we logged on with) to access the folders and files in the rootdirectory.
I am in a situation where I need to copy files onto the share point server. I want to be able to copy files onto the server without using the mapped network drive (not have to specify Z:\ in the path). How can I supply credentials so that I can perform basic IO functions like GetDirectories(), GetFiles(), IO.File.Copy() etc...?
I have looked into the following things but was unsuccessful in making them work:
LogonUser API call by specifying plain text user name and password, then taking the token from that call and impersonating that user using a new instance of the WindowsIdentity class. Was able to get the token, but the impersonation didn't seem to work. Kept getting access denied errors.
CredUIPromptForCredentials/CredUIPromptForWindowsCredentials API calls, but I realize these are just for a fancy Windows UI where you can enter your credentials into and actually don't do anything.
<DllImport("advapi32.dll", SetLastError:=True)> _
Private Shared Function LogonUser(lpszUsername As String, lpszDomain As String, _
lpszPassword As String, dwLogonType As Integer, _
dwLogonProvider As Integer, ByRef phToken As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function CloseHandle(handle As IntPtr) As Boolean
End Function
'// logon types
Public Const LOGON32_LOGON_NETWORK As Integer = 3
Public Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
'// logon providers
Public Const LOGON32_PROVIDER_WINNT50 As Integer = 3
Public Const LOGON32_PROVIDER_WINNT40 As Integer = 2
Public Const LOGON32_PROVIDER_WINNT35 As Integer = 1
Public Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim token = IntPtr.Zero
Dim success = LogonUser("username", "domain", "password", _
LOGON32_LOGON_NEW_CREDENTIALS, _
LOGON32_PROVIDER_DEFAULT, token)
If Not success Then
Me.RaiseLastWin32Error()
End If
Using identity = New WindowsIdentity(token)
Using impersonated = identity.Impersonate()
Try
Dim info = New DirectoryInfo("\\theserver.ourdomain.com\rootdirectory\")
Dim files = info.GetDirectories()
Catch ex As Exception
Finally
impersonated.Undo()
End Try
If Not CloseHandle(token) Then
Me.RaiseLastWin32Error()
End If
End Using
End Using
End Sub
Private Sub RaiseLastWin32Error()
Dim hr = Marshal.GetLastWin32Error()
Dim ex = Marshal.GetExceptionForHR(hr)
If ex IsNot Nothing Then
Throw ex
End If
Throw New SystemException(String.Format("Call resulted in error code {0}", hr))
End Sub
This isn't a direct answer to your question as it is a wildly different approach. If it doesn't work for your situation sorry to bother, but have you considered using the SharePoint web services to load the files and retrieve information?
I suggest this approach for a few reasons:
The issue you are experiencing may be occurring because SharePoint implements WebDav which might not be 100% compatible with System.IO. I'm not an expert on the innards here, I don't know about the compatibility for sure, but it seems plausible.
The UNC location you have could easily be massaged into a URL that the web service requires.
You can set the credentials directly on the proxy and might have an easier time. (though we make these calls from another web server and so the app pool credentials in the example are good enough for us)
Here's some sanitized and simplified code just in case:
// location takes the form http://server.name.com/site/library/folder/document.ext
public string UploadDocument(string location, byte[] fileContents)
{
var result = String.empty;
var destination = new string[1];
destination[0] = location;
var fileName = Path.GetFileName(location);
var fieldInfo = new FieldInformation[0];
CopyResult[] copyResults;
_copyService.Url = "http://server.name.com/_vti_bin/Copy.asmx";
_copyService.Credentials = CredentialCache.DefaultCredentials;
_copyService.CopyIntoItems(fileName, destination, fieldInfo, fileContents, out copyResults);
var errorCode = copyResults[0].ErrorCode;
if (errorCode != CopyErrorCode.Success)
{
if (errorCode == CopyErrorCode.DestinationCheckedOut)
result = "File is currently checked out. Please try again later.";
else
result = "Error uploading content.";
}
return result;
}
_copyService is a dependency we inject where the run-time implementation is the proxy generated by Visual Studio tools from the Copy.asmx SharePoint web service.
You can also get folder contents and document metadata using the Lists.asmx web service. The biggest downsides to this approach are that querying the information requires some CAML knowledge and processing the results is not as easy. But the services are reasonably documented on MSDN and the operations are all working in our application.
Well, I was able to solve this with the help of the WNetAddConnection2 API. This API is used for mapping network drives as well, however you can call this method without specifying a drive letter so that it just adds the connection.
Say for example you had drive X: mapped to \\server\share
Lets also say that it requires username & password to access the files on the server. When you restart Windows 7, you will probably lose that connection (you will get a notification saying that Windows was unable to reconnect some of the network drives). If you have an application that requires access to that server's files and you attempt to access it without supplying your credentials you will get access denied exceptions. If you do a successful call to WNetAddConnection2, not only will it fix your unmapped network drive, you will also be able to access the files/directories via the System.IO namespace.
We use Sharepoint and this worked for me. Thanks to the other guys for replying also.