I'm trying send XML document to a page .asp, and get the answer, but I get following error:
System.UriFormatException: Invalid URI: The URI scheme is not valid. at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind) at System.Net.WebRequest.Create(String requestUriString) at GNS_ZalkarBank.GNSTaskServiceZalkarBank.CreateRequest(String requestData, String address) at GNS_ZalkarBank.GNSTaskServiceZalkarBank.SendRequest(String requestString, String address) at GNS_ZalkarBank.GNSTaskServiceZalkarBank.processData(TaskInfo& taskInfo, Object& data) at Task.RegistryTemplate.RegistryTaskTemplate.execute(DataSet& dataSet)`
I implemented a method for sending data to a page with asp server script:
private string SendRequest(String requestString, String address)
{
address = "https://myadress/osmp_gni_xml.asp";
HttpWebRequest httpRequest = this.CreateRequest(requestString, address);
string response = GetResponse(httpRequest);
return response;
}
private HttpWebRequest CreateRequest(string requestData, string address)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
request.Method = "POST";
//request.UserAgent = "Test";
byte[] data = Encoding.UTF8.GetBytes(requestData);
request.ContentType = "text/xml; encoding='utf-8'";
request.ContentLength = data.Length;
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(data, 0, data.Length);
dataStream.Close();
}
return request;
}
private string GetResponse(HttpWebRequest httpWebRequest)
{
string responseString;
HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();
using (Stream dataStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
{
responseString = reader.ReadToEnd();
}
}
return responseString;
}
Server side (script page: osmp_gni_xml.asp):
<%# Language=VBScript CODEPAGE="65001"%>
<%
Sub AddSubNode(Parent, Name, Value)
Set subNode = XMLDoc.createElement(Name)
Parent.appendChild(subNode)
subNode.appendChild(XMLDoc.createTextNode(Value))
End Sub
Function Stream_BinaryToString(Binary, CharSet)
Const adTypeText = 2
Const adTypeBinary = 1
'Create Stream object
Dim BinaryStream 'As New Stream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save text/string data.
BinaryStream.Type = adTypeBinary
'Open the stream And write text/string data To the object
BinaryStream.Open
BinaryStream.Write Binary
'Change stream type To binary
BinaryStream.Position = 0
BinaryStream.Type = adTypeText
'Specify charset For the source text (unicode) data.
If Len(CharSet) > 0 Then
BinaryStream.CharSet = CharSet
Else
BinaryStream.CharSet = "us-ascii"
End If
'Open the stream And get binary data from the object
Stream_BinaryToString = BinaryStream.ReadText
End Function
result=300
OK="incomplete request"
Dim PostData
Dim biData
PostData = ""
If Request.TotalBytes>0 Then
biData = Request.BinaryRead(Request.TotalBytes)
PostData=Stream_BinaryToString(biData, "utf-8")
ProvStr = "Provider=sqloledb;Data Source=TEST;Initial Catalog=TESTOsmp;User Id=tests_osmp;Password=tests;"
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open ProvStr
Set cmdUA = Server.CreateObject("ADODB.Command")
cmdUA.ActiveConnection = Conn
cmdUA.CommandText = "GNI_Import"
cmdUA.CommandType = 4
cmdUA.Parameters.Append cmdUA.CreateParameter("Reestr", 202, 1, 2000, PostData)
Set RS = cmdUA.Execute
result = RS("result")
RS.Close
Conn.Close
Set Conn = Nothing
Set RS = Nothing
End If
'Create XML
Set XMLDoc = Server.CreateObject("Microsoft.XMLDOM")
Set pi = XMLDoc.createProcessingInstruction("xml"," version=""1.0"" encoding=""utf-8""")
XMLDoc.appendChild(pi)
'Main
Set mainNode = XMLDoc.createElement("response")
XMLDoc.appendChild(mainNode)
If result=0 Then
OK="Ok"
Else
result=300
OK="incomplete request"
End If
AddSubNode mainNode, "result", result
AddSubNode mainNode, "comment", OK
Response.ContentType = "text/xml"
Response.Write XMLDoc.XML
Set mainNode = Nothing
Set XMLDoc = Nothing
%>
Whats wrong?
The provided error text comes from here:
private HttpWebRequest CreateRequest(string requestData, string address)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address); // <- THIS LINE
...
}
The error description is complaining that the address https://myadress/osmp_gni_xml.asp is invalid, being https the most likely causes are connection issues.
Trying to connect via https but not having setup https server-side in the first place is very common: verify the address is reachable, security is properly setup, and the sort. A console tool like F12 developer console (part of IE9), FireBug (Firefox extension) or Fiddler (desktop application) are the best tools to find out what's happening when it comes to external connections.
I suspect the code you've provided isn't the code that has the problem, see this:
private string SendRequest(String requestString, --> String address <--)
{
--> address = "https://myadress/osmp_gni_xml.asp"; <--
HttpWebRequest httpRequest = this.CreateRequest(requestString, address);
string response = GetResponse(httpRequest);
return response;
}
You're passing address to the method but then hard-wiring it on the first line. The problem's with the format of address, but it probably won't exist with this code.
What may be happening is that you're reading the address from a file or database and as a human you're seeing "https://myadress/osmp_gni_xml.asp" because you're using a flawed unescaping mechanism but what the code is seeing is something like:
https/:////myaddress//osmp_gni_xml.asp
which gives the same error.
In your actual code, what is the exact value of address in the place where you've overwritten it in SendRequest
Related
I have jobs in Jenkins that i cannot access unless i log in first using a my username and password.
For example if i try to access "localhost:xxx/job/some_job_1" i will get a 404 Error unless i log in first. And i say this because i have tried the following using WebRequest class:
string formParams = "j_username=bobbyLee&j_password=SecretPassword25&from=%2F&json=%7B%22j_username%22%3A+%bobbyLee%22%2C+%22j_password%22%3A+%22SecretPassword%25%22%2C+%22remember_me%22%3A+false%2C+%22from%22%3A+%22%2F%22%7D&Submit=log+in";
// ***this is the exact string that is sent when i log in normally, obtained using Fiddler***
string formUrl = "http://serverName:PortNum/j_acegi_security_check";
// ***I have also tried http://serverName:PortNum/login***
string cookieHeader;
WebRequest req = WebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
string pageSource;
string getUrl = "http://serverName:portNum/job/some_job/";
WebRequest getRequest = WebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
WebResponse getResponse = getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
The response that i get back from the POST request is "HTML OK", and cookieHeader is not null. But when i then try to make a GET request to get what i want, i get a 404 error when attempting to access the job "http://serverName:portNum/job/some_job/", as if i didn't log in successfully.
So what is the correct way to log into Jenkins from c#, and get the HTML source code of the jobs that only appears after logging in?
The RESTAPI is your best friend here.
It is an incredibly rich source of information. I have written a system that will show an entire program of work on a page with full deployment traceability.
I am going to assume you have some security in place in your Jenkins instance which means requests need to be authenticated.
I use the following class for this:
using System;
using System.Net;
using System.Text;
namespace Core.REST
{
public class HttpAdapter
{
private const string ApiToken = "3abcdefghijklmnopqrstuvwxyz12345"; // you will need to change this to the real value
private const string UserName = "restapi";
public string Get(string url)
{
try
{
const string credentials = UserName + ":" + ApiToken;
var authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
using (var wc = new WebClient())
{
wc.Headers[HttpRequestHeader.Authorization] = "Basic " + authorization;
var htmlResult = wc.DownloadString(string.Format(url));
return htmlResult;
}
}
catch (WebException e)
{
Console.WriteLine("Could not retrieve REST API response");
throw e;
}
}
}
}
restapi is a dedicated user I created. I think I gave it admin access just so I didn't have to worry about it. I was admin but all the other developers and testers in the 3 crews had highly controlled and limited access to only what they needed and nothing more. It is also better practice to have a dedicated users for functions like this.
I constructed my c# classes to consume (deserialise) data from any page that supports the api/json suffix.
I have a user controller created using the hartl tutorial that signs up new users via form with email and password inputs. This is working properly. I am attempting to send an HttpWebRequest from the Unity editor player to my server in order to sign up a new user from a password string created within Unity. I have provided the error response and the code relevant to the attempt below.
WebException: The remote server returned an error: (422) Unprocessable Entity.
System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult asyncResult) (at ><4b9f316768174388be8ae5baf2e6cc02>:0)
System.Net.HttpWebRequest.GetResponse () (at <4b9f316768174388be8ae5baf2e6cc02>:0)
UnityStandardAssets.Characters.RigidbodyFirstPersonController.RigidbodyFirstPer>sonController.resetScene3 () (at >Assets/Scripts/RigidbodyFirstPersonController.cs:463)
HttpWebRequest Code from RigidbodyFirstPer>sonController.resetScene3 ():
public static string _url = "https://immense-castle-53592.herokuapp.com/signup";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(_url);
request.Method = "POST";
request.Headers ["action"] = "/users";
request.Headers ["class"] = "new_user";
request.Headers ["id"] = "new_user";
request.Headers ["utf8"] = "✓";
request.Headers ["authenticity_token"] = "NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=";
request.Headers ["user_email"] = "jakebrantley44#gmail.com";
request.Headers ["user_password"] = passwordUnity;
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Debug.Log("Publish Response: " + (int)response.StatusCode + ", " + response.StatusDescription);
if((int)response.StatusCode == 200)
{
//SetEnvironmentVersion(version);
}
}
Ruby on Rails Users Controller
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
puts params[:password]
if #user.save
log_in #user
flash[:success] = "Welcome to your vault!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:email, :password)
end
end
Routes.rb
Rails.application.routes.draw do
get 'sessions/new'
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/demo', to: 'static_pages#demo'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
post '/signup', to: 'users#create'
post '/', to: 'users#create'
get '/show', to: 'users#create'
delete '/logout', to: 'sessions#destroy'
resources :users
end
Update: New code from attempt utilizing Stream.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(_url);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
// Add dictionary strings
headers["action"] = "/users";
headers["class"] = "new_user";
headers["id"] = "new_user";
headers["utf8"] = "✓";
headers["authenticity_token"] = "NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=";
headers["user_email"] = "jakebrantley44#gmail.com";
headers["user_password"] = passwordUnity;
byte[] headersByte = UnityWebRequest.SerializeSimpleForm(headers);
// Set the ContentLength property of the WebRequest.
request.ContentLength = headersByte.Length;
Debug.Log( headersByte );
// Get the request stream.
Stream dataStream = request.GetRequestStream ();
// Write the data to the request stream.
dataStream.Write (headersByte, 0, headersByte.Length);
// Close the Stream object.
dataStream.Close ();
// Get the response.
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// Display the status.
Console.WriteLine (((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream ();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader (dataStream);
//Read the content
string responseFromServer = reader.ReadToEnd ();
// Display the content.
Console.WriteLine (responseFromServer);
Debug.Log(responseFromServer);
reader.Close ();
dataStream.Close ();
response.Close ();
Debug.Log("Publish Response: " + (int)response.StatusCode + ", " + response.StatusDescription);
if((int)response.StatusCode == 200)
{
}
}
The ruby code is looking for the params :email and :password, but in the client side, you are adding user_email and user_password to the header instead.
Also based on the updated code, I think you should put
if((int)response.StatusCode == 200)
{
}
before response.Close();.
Solved it!
Changed method of post from Http.Web.Request to UnityWebRequest. Http.Web.Request headers aren't intended to be used for passing parameters.
Changed Ruby/Rails users_controller.rb user_params function to the following. The controller needed to be set to .fetch the parameter values:
def user_params
puts "user_params runs"
unless params["user"].blank?
puts "main state user_params"
params.fetch(:user, {:email => params[:EMAIL], :password => params[:PASSWORD]}).permit(:email, :password)
end
puts "unless state in user_params"
params.fetch(:user, {"email"=>params[:EMAIL], "password"=>params[:PASSWORD]}).permit(:email, :password)
end
After I create connection, I need to send IDs and then store response, then send again and again (usually ~60-100 IDs). Currently I did it this way:
public void EThread()
{
HttpWebRequest HWRequest = (HttpWebRequest)WebRequest.Create(_AjaxURL);
HWRequest.Method = "POST";
HWRequest.ContentType = "text/xml; encoding='utf-8'";
string StrID;
while(!_RequiredIDs.IsEmpty)
if (_RequiredIDs.TryDequeue(out StrID))
Extract(StrID, ref HWRequest);
}
public void Extract(string ID, ref HttpWebRequest HWRequest)
{
string data = "strID=" + ID;
byte[] Bytes = Encoding.ASCII.GetBytes(data);
using (Stream SWriter = HWRequest.GetRequestStream())
{
SWriter.Write(Bytes, 0, Bytes.Length);
SWriter.Close();
}
HttpWebResponse resp = (HttpWebResponse)HWRequest.GetResponse();
using (Stream s = resp.GetResponseStream())
using (StreamReader sr = new StreamReader(s))
_RespnseCollection.Enqueue(sr.ReadToEnd());
}
However, I got this error: System.Net.WebException: 'The request was aborted: The connection was closed unexpectedly.. If I put HttpWebRequest inside Extract method it works, but that works long. This was checked on 1 thread. What is wrong with the code or the server does not support this.
The problem is that you are re-using the HWRequest. But an HttpWebRequest is a single use item. In other words you can fire off the request only once.
So if thr _RequiredIDs contains more than one item, the first item will work properly, but change the state of the HwRequest to completed (ie it now contains a response) and the HaveResponse property will be set to true.
If you then again execute GetRequestStream()or GetResponse() it determines that, having already received a response, it does not make sense to set up the request again.
So you could modify your code as follows:
public void EThread()
{
string StrID;
while(!_RequiredIDs.IsEmpty)
if (_RequiredIDs.TryDequeue(out StrID))
{
HttpWebRequest HWRequest = (HttpWebRequest)WebRequest.Create(_AjaxURL);
HWRequest.Method = "POST";
HWRequest.ContentType = "text/xml; encoding='utf-8'";
Extract(StrID, ref HWRequest);
}
}
BUT, I suppose this is really functionally equivalent to declaring the HttpRequest and initializing inside the Extract method.
SUGGESTIION:
Try calling HWRequest.Reset():
public void EThread()
{
HttpWebRequest HWRequest = (HttpWebRequest)WebRequest.Create(_AjaxURL);
HWRequest.Method = "POST";
HWRequest.ContentType = "text/xml; encoding='utf-8'";
string StrID;
while(!_RequiredIDs.IsEmpty)
if (_RequiredIDs.TryDequeue(out StrID))
{
Extract(StrID, ref HWRequest);
HWRequest.Reset();
}
}
I am having some trouble trying to write code within a RESTful WCF service. I have made a method available to a calling client application and I am receiving a message that is of the format Ax27834...... which is a Base64 Binary message. The issue is that following receiving this I need to be able to convert it back to the original xml version of that message that was sent from the client. How can I achieve this in the code snippet below. On line 6 below you will see where the code needs to go. I have searched for a solution but not managed to find anything suitable. I have to receive a message rather than a stream.
I should highlight that the service works fine in the respect of receiving the request. I am just struggling to get the message into a form that I can use.
The receiving code
public Message StoreMessage(Message request)
{
//Store the message
try
{
string message = [NEED SOLUTION HERE]
myClass.StoreNoticeInSchema(message, DateTime.Now);
}
catch (Exception e)
{
log4net.Config.XmlConfigurator.Configure();
ILog log = LogManager.GetLogger(typeof(Service1));
if (log.IsErrorEnabled)
{
log.Error(String.Format("{0}: Notice was not stored. {1} reported an exception. {2}", DateTime.Now, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, e.Message));
}
}
XElement responseElement = new XElement(XName.Get("elementName", "url"));
XDocument resultDocument = new XDocument(responseElement);
return Message.CreateMessage(OperationContext.Current.IncomingMessageVersion, "elementName", resultDocument.CreateReader());
}
The client code
public string CallPostMethod()
{
const string action = "StoreNotice/New";
TestNotice testNotice = new TestNotice();
const string url = "http://myaddress:myport/myService.svc/StoreNotice/New";
string contentType = String.Format("application/soap+xml; charset=utf-8; action=\"{0}\"", action);
string xmlString = CreateSoapMessage(url, action, testNotice.NoticeText);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytesToSend = encoding.GetBytes(xmlString);
request.Method = "POST";
request.ContentLength = bytesToSend.Length;
request.ContentType = contentType;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytesToSend, 0, bytesToSend.Length);
requestStream.Close();
}
string responseFromServer;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream dataStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
responseFromServer = reader.ReadToEnd();
dataStream.Close();
}
XDocument document = XDocument.Parse(responseFromServer);
string nameSpace = "http://www.w3.org/2003/05/soap-envelope";
XElement responseElement = document.Root.Element(XName.Get("Body", nameSpace))
.Element(XName.Get(#action + "Response", "http://www.wrcplc.co.uk/Schemas/ETON"));
return responseElement.ToString();
}
Code to create SOAP message
protected string CreateSoapMessage(string url, string action, string messageContent)
{
return String.Format(
#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope""><soap12:Body>{0}</soap12:Body>
</soap12:Envelope>
", messageContent, action, url);
}
NOTE: The TestNotice() object contains a large xml string which is the body of the message.
With a Message object you usually use GetReaderAtBodyContents() to get an XML representation of the body content, unless you know what type the body has then you can use GetBody<>. Try using those to get the string, and then decode it if you still need to. Which you can do as follows:
byte[] encodedMessageAsBytes = System.Convert.FromBase64String(requestString);
string message = System.Text.Encoding.Unicode.GetString(encodedMessageAsBytes);
From there you can reconstruct the xml from the string
Edit: to answer the last part from the comment, the content type should be: text/xml
I've got a problem with creating an HTTP post request in .NET. When I do this request in ruby it does work.
When doing the request in .NET I get following error:
<h1>FOXISAPI call failed</h1><p><b>Progid is:</b> carejobs.carejobs
<p><b>Method is:</b> importvacature/
<p><b>Parameters are:</b>
<p><b> parameters are:</b> vacature.deelnemernr=478
</b><p><b>GetIDsOfNames failed with err code 80020006: Unknown name.
</b>
Does anyone knows how to fix this?
Ruby:
require 'net/http'
url = URI.parse('http://www.carejobs.be/scripts/foxisapi.dll/carejobs.carejobs.importvacature')
post_args = {
'vacature.deelnemernr' => '478',
}
resp, data = Net::HTTP.post_form(url, post_args)
print resp
print data
C#:
Uri address = new Uri(url);
// Create the web request
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
// Set type to POST
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// Create the data we want to send
StringBuilder data = new StringBuilder();
data.Append("vacature.deelnemernr=" + HttpUtility.UrlEncode("478"));
// Create a byte array of the data we want to send
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString());
// Set the content length in the request headers
request.ContentLength = byteData.Length;
// Write data
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Console application output
result = reader.ReadToEnd();
}
return result;
Don't you need the ? after the URL in order to do a post with parameters? I think that Ruby hides this behind the scenes.
I found the problem! The url variable in the C# code was "http://www.carejobs.be/scripts/foxisapi.dll/carejobs.carejobs.importvacature/"
It had to be "http://www.carejobs.be/scripts/foxisapi.dll/carejobs.carejobs.importvacature" without the backslash.