Reading external XML via a proxy - c#

I want to read some external xml, but I have to connect via a proxy, but I'm not sure how to do it. I have the following code, the xmlurl contains a path to the external xml:
if (content > 0)
{
using (XmlTextReader xml = new XmlTextReader(xmlurl))
{
while (xml.Read())
{
Console.WriteLine(xml.Name);
}
}
}
I had the following proxy code for another HttpWebRequest piece I had:
if(Convert.ToBoolean(ConfigurationManager.AppSettings["behindproxy"]) == true)
{
WebProxy proxy = new WebProxy();
Uri proxyUri = new Uri("srvisa01");
proxy.Address = proxyUri;
proxy.BypassProxyOnLocal = true;
proxy.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["proxyusername"].ToString(), ConfigurationManager.AppSettings["proxypassword"].ToString());
}
But I'm not sure this will work in this case.
Help appreciated.
Kind regards
Chris

I found the answer to this question with some determined Googling:
XmlTextReader xml;
WebRequest web;
web = WebRequest.Create(xmlurl);
if(Convert.ToBoolean(ConfigurationManager.AppSettings["behindproxy"].ToString()))
{
WebProxy prxy = new WebProxy();
Uri prxyUri = new Uri("http://xxx:8080");
prxy.Address = prxyUri;
prxy.BypassProxyOnLocal = true;
prxy.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["proxyusername"].ToString(), ConfigurationManager.AppSettings["proxypassword"].ToString());
web.Proxy = prxy;
}
var response = web.GetResponse().ToString();
xml = new XmlTextReader(response);
Hope this answer helps peeps :)

Related

Call All Operations In ASMX Programmatically

Assume there exists a generic string collection that contains a variety of web service URLs:
List<string> webServiceCollection = new List<string>();
webServiceCollection.Add("http://<site>/_vti_bin/Lists.asmx");
webServiceCollection.Add("http://<site>/_vti_bin/Sites.asmx");
There a variety of methods, with a variety of input and return types in each web service. Is it possible to read the all the available operations and attempt the operation with default values? For this purpose, I am trying to write a security tool that will help test whether the web service allows the user to interact with them under a variety of accounts as an academic exercise.
You can do something like this:
PSEUDO CODE
System.Net.WebClient client = new System.Net.WebClient();
string strUrl = #"http://localhost:xxxxx/Service.asmx?wsdl";
System.IO.Stream stream = client.OpenRead(strUrl);
string serviceName = "Service";
// Get a WSDL file describing a service.
ServiceDescription description = ServiceDescription.Read(stream);
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap12"; // Use SOAP 1.2.
importer.AddServiceDescription(description, null, null);
// Generate a proxy client.
importer.Style = ServiceDescriptionImportStyle.Client;
// Generate properties to represent primitive values.
importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
// Initialize a Code-DOM tree into which we will import the service.
CodeNamespace nmspace = new CodeNamespace();
CodeCompileUnit unit1 = new CodeCompileUnit();
unit1.Namespaces.Add(nmspace);
// Import the service into the Code-DOM tree. This creates proxy code
// that uses the service.
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
if (warning == 0)
{
// Generate and print the proxy code in C#.
CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
// Compile the assembly with the appropriate references
string[] assemblyReferences = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters parms = new CompilerParameters(assemblyReferences);
CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
foreach (CompilerError oops in results.Errors)
{
Console.WriteLine("========Compiler error============");
Console.WriteLine(oops.ErrorText);
}
//Invoke the web service method
foreach (PortType portType in description.PortTypes)
{
foreach (Operation operation in portType.Operations)
{
try
{
object o = results.CompiledAssembly.CreateInstance(serviceName);
Type t = o.GetType();
Console.WriteLine(t.InvokeMember(operation.Name, System.Reflection.BindingFlags.InvokeMethod, null, o, null));
}catch(Exception ex){
Console.WriteLine(ex.Message);
}
}
}
}
else
{
// Print an error message.
Console.WriteLine("Warning: " + warning);
}
this will be your best attempt to try and achieve your goal:
string completeUrl ="http://localhost/testwebservice";
// Create a request for the URL.
WebRequest request = WebRequest.Create(completeUrl);
// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;
// If you have a proxy configured.
WebProxy proxyObject = new WebProxy("http://proxy.com/", true);
request.Proxy = proxyObject;
//Get the response.
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// Get the stream containing content returned by the server.
using(Stream dataStream = response.GetResponseStream())
{
// Open the stream using a StreamReader for easy access.
using(StreamReader reader = new StreamReader(dataStream))
{
// Read the content.
string responseFromServer = reader.ReadToEnd();
}
}
}
and in order to add your try you should do:
List<string> webServiceCollection = new List<string>();
webServiceCollection.Add("http://<site>/_vti_bin/Lists.asmx");
webServiceCollection.Add("http://<site>/_vti_bin/Sites.asmx");
foreach(var reqeust in webServiceCollection)
{
string completeUrl = $"{request}";;
// Create a request for the URL.
WebRequest request = WebRequest.Create(completeUrl);
// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;
// If you have a proxy configured.
WebProxy proxyObject = new WebProxy("http://proxy.com/", true);
request.Proxy = proxyObject;
//Get the response.
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// Get the stream containing content returned by the server.
using(Stream dataStream = response.GetResponseStream())
{
// Open the stream using a StreamReader for easy access.
using(StreamReader reader = new StreamReader(dataStream))
{
// Read the content.
string responseFromServer = reader.ReadToEnd();
}
}
}
}

Get GitHub Rest API User info C# code

https://api.github.com/users/[UserName] can be accessed via browser. I get a Json result. But I want to retrieve the same information programmatically.
I'm using the below code, which is not working as expected. Please advice.
var credentials =
string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}:",
githubToken);
credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Basic", credentials);
var contents =
client.GetStreamAsync("https://api.github.com/users/[userName]").Result;
As a result of the above code, I'm getting "Aggregate Exception".
How to achieve the requirement using c# code??? Please help
Note: Not expecting a solution with Octokit. Need proper c# code.
I found the solution. Here is the code.
HttpWebRequest webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
if (webRequest != null)
{
webRequest.Method = "GET";
webRequest.UserAgent = "Anything";
webRequest.ServicePoint.Expect100Continue = false;
try
{
using (StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
string reader = responseReader.ReadToEnd();
var jsonobj = JsonConvert.DeserializeObject(reader)
}
}
catch
{
return;
}
}

Set proxy for Google.Apis.YouTube.v3

I have the following bit of code to make a call to the
YouTubeService service = new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = AppSettings.Variables.YouTube_APIKey,
ApplicationName = AppSettings.Variables.YouTube_AppName
});
Google.Apis.YouTube.v3.VideosResource.ListRequest request = service.Videos.List("snippet,statistics");
request.Id = string.Join(",", videoIDs);
VideoListResponse response = request.Execute();
This all works but when we deploy it to our live server, it needs to get through a proxy so we put the following into the web.config:
<defaultProxy useDefaultCredentials="false" enabled="true">
<proxy usesystemdefault="False" proxyaddress="http://192.111.111.102:8081" />
</defaultProxy>
However, this doesn't seem to be working as when the call is made, I get the following error:
System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 216.58.213.74:443
Is there a way to manually set the proxy in code?
Something along the lines of:
WebProxy proxy = new WebProxy("192.111.111.102", 8081);
proxy.Credentials = new NetworkCredential(AppSettings.Variables.ProxyUser, AppSettings.Variables.ProxyPassword, AppSettings.Variables.ProxyDomain);
// apply this to the service or request object here
Yes of course!
You can set a System.Net.WebProxy for a YouTubeService instance:
var _youtubeService = new YouTubeService(yourInitializer);
_youtubeService.HttpClient.MessageHandler.InnerHandler = new HttpClientHandler
{
Proxy = new WebProxy(your parameters..)
};
NOTE : Don't forget to set other HttpClientHandler properties if needed(for example AutomaticDecompression)
To get around this I had to make a webrequest to the url and map the result back to the VideoListResponse object:
try
{
Uri api = new Uri(string.Format("https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&part=snippet,statistics", videoIds, AppSettings.Variables.YouTube_APIKey));
WebRequest request = WebRequest.Create(api);
WebProxy proxy = new WebProxy(AppSettings.Variables.ProxyAddress, AppSettings.Variables.ProxyPort);
proxy.Credentials = new NetworkCredential(AppSettings.Variables.ProxyUsername, AppSettings.Variables.ProxyPassword, AppSettings.Variables.ProxyDomain);
request.Proxy = proxy;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
return JsonConvert.DeserializeObject<VideoListResponse>(streamReader.ReadToEnd());
}
}
}
catch (Exception ex)
{
ErrorLog.LogError(ex, "Video entity processing error: ");
}
The solution of #ABS looks more efficient and "compact" to me.
Here's how i use it in VB.NET with the Youtube Channel API:
Dim uriProxy As New Uri("*proxy_url:IP*")
Dim wpyProxy As New WebProxy With {.Address = uriProxy }
Dim get_youtube_channel_channel_work As New youtube_channel
Dim youtube_initialiser As New Google.Apis.Services.BaseClientService.Initializer()
youtube_initialiser.ApiKey = ConfigurationManager.AppSettings("youtube_api_key")
youtube_initialiser.ApplicationName = ConfigurationManager.AppSettings("youtube_api_application_name")
Dim youtube_service As Google.Apis.YouTube.v3.YouTubeService = New YouTubeService(youtube_initialiser)
Dim objChannelListRequest As ChannelsResource.ListRequest = youtube_service.Channels.List("id, snippet, statistics")
youtube_service.HttpClient.MessageHandler.InnerHandler = New HttpClientHandler With {.Proxy = wpyProxy}

How to speed up slow GetResponse and GetRequest?

I have a web site in ASP.NET C# that is running pretty slow in one spot. When I used a profiler to examine it the two spots of slowness are GetResponse and GetRequest. I am connecting to a 3rd party system to get availability on a calendar so I'm communicating with them through a POST. We have a counterpart that is in ASP classic and it seems faster but I have no easy way to profile it.
I am sending an XML string byte-encoded that's around 440 bytes, depending on a few things and the return is under 2k. I'm including most of the relevant routines here. I tried setting the default Proxy to GetEmptyWebProxy in case that would help as I read it could.
It is taking 2 to 5 seconds to process the request/response. The pressure is on because the boss is counting hippopotamuses and I can't get real stats on the Classic version so it's all perception at this point.
My question is this - Am I going about as fast as I can and it's the nature of the beast or is there something I can do to speed up this communications? Any help greatly appreciated.
Here's some code:
protected void UpdateInventory(DateTime _SelectedDate)
{
// build request object
Envelope _Request = new Envelope();
_Request.Body = new Body();
_Request.Body.QueryEvents = new QueryEvents();
_Request.Header = new Header();
//setup search criteria for API request
_Request.Body.QueryEvents.EventRangeBeginDate = _SelectedDate.ToString(_DTFormat);
_Request.Body.QueryEvents.EventRangeEndDate = _SelectedDate.AddDays(1).ToString(_DTFormat);
_Request.Body.QueryEvents.EventTypeID = _EventTypeId;
_Request.Header.SourceID = "BackOffice";
_Request.Header.MessageID = 0;
_Request.Header.MessageType = "QueryEvents";
_Request.Header.TimeStamp = LocaleHelper.LocalNow.ToString(_DTFormat);
_Request.Header.EchoData = "BO Calendar";
// send API request
HttpStatusCode _Status = GetGatewayInventory(_Request);
}
protected HttpStatusCode GetGatewayInventory(Envelope _InvRequest)
{
// set up return value
HttpStatusCode _RetVal = HttpStatusCode.Unused;
// initialize global inventory object
_Inventory = new Envelope();
// serialize request object into XML
XmlSerializer _Serializer = new XmlSerializer(_InvRequest.GetType());
MemoryStream _Stream = new MemoryStream();
_Serializer.Serialize(_Stream, _InvRequest);
XmlDocument _Doc = new XmlDocument();
_Stream.Position = 0;
_Doc.Load(_Stream);
// remove unneeded info.
XmlNode _Node = _Doc.SelectSingleNode("/Envelope");
XmlElement _ENode = (XmlElement)_Node;
_ENode.RemoveAttribute("xmlns:xsi");
_ENode.RemoveAttribute("xmlns:xsd");
// clean up
string _XmlStr = _Doc.InnerXml.Replace("\"1.0\"", "'1.0'");
byte[] _Bytes = System.Text.Encoding.ASCII.GetBytes(_XmlStr);
// send string to gateway
// set web request
string _GWHost = _GatewayHostLive;
HttpWebRequest _req = (HttpWebRequest)WebRequest.Create(_GWHost);
IWebProxy myProxy = GlobalProxySelection.GetEmptyWebProxy();
GlobalProxySelection.Select = myProxy;
_req.Proxy = myProxy;
_req.Method = "POST";
_req.ContentLength = _Bytes.Length;
_req.ContentType = "text/xml; encoding='utf-8'";
Stream _RequestStream = _req.GetRequestStream();
_RequestStream.Write(_Bytes, 0, _Bytes.Length);
_RequestStream.Close();
using (HttpWebResponse _Resp = (HttpWebResponse)_req.GetResponse())
{
_RetVal = _Resp.StatusCode;
if (_Resp.StatusCode == HttpStatusCode.OK)
{
Stream _respStream = _Resp.GetResponseStream();
XmlTextReader _xmlreader = new XmlTextReader(_respStream);
XmlDocument _RespXml = new XmlDocument();
_RespXml.Load(_xmlreader);
_xmlreader.Close();
// deserialize back into object
StringReader _sr = new StringReader(_RespXml.InnerXml);
XmlSerializer _XmlSr = new XmlSerializer(_Inventory.GetType());
XmlReader _Inreader = new XmlTextReader(_sr);
_Inventory = (Envelope)_XmlSr.Deserialize(_Inreader);
StripExtrasIfOnlyShowFirstAvailable(_Inventory, CountTotalTickets());
grd_EventTimes.DataSource = _Inventory.Body.Events.Event;
grd_EventTimes.DataBind();
grd_EventTimes.Visible = true;
if (_Inventory.Body.Events.Event.Count > 0)
lbl_GatewayId.Text = "GN: " + _Inventory.Body.Events.Event[0].EventName + " ID:" + _EventTypeId ;
}
_Resp.Close();
}
// exit and return value
return _RetVal;
}
You can try to disable the Nagle algorithm via ServicePointManager.UseNagleAlgorithm = false, see MSDN.
The (bad) effects of Nagle can add at least half a second of extra delay to your POST request. It mixes badly with small POST requests since those do two writes to the underlying TCP stream before waiting for (reading) the response. See details in the Nagle Wikipedia link.

Can I create dynamic web service client reference without adding its reference to service references of the project?

I need to create dynamic references of multiple web services and sent some value with it.
To be truly dynamic, you have to do three things:
1) Get the service description (wsdl) from the web service
2) Generate the proxy code dynamically from the service description
3) Compile the code and expose it in your application - usually through reflection or some sort of dynamic scripting interface.
The code snippet below is from some experimenting I did a long time ago. It is not production code and won't compile, but should give you a head start if this is the direction you want to go.
It does not include step (3). The code generated can be compiled with classes provided in the System.CodeDom.Compiler namespace.
Uri uri = new Uri(_Url + "?wsdl");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AllowAutoRedirect = true;
request.PreAuthenticate = false;
if (_User.Length > 0)
{
request.UseDefaultCredentials = false;
request.Credentials = new NetworkCredential(_User, _Password, _Domain);
}
WebResponse response = null;
try
{
response = request.GetResponse();
}
catch (System.Net.WebException wex)
{
response = wex.Response;
}
catch (Exception ex)
{
}
Stream requestStream = response.GetResponseStream();
ServiceDescription sd = ServiceDescription.Read(requestStream);
_ReferenceName = _Namespace + "." + sd.Services[0].Name;
ServiceDescriptionImporter Importer = new ServiceDescriptionImporter();
Importer.AddServiceDescription(sd, string.Empty, string.Empty);
Importer.ProtocolName = "Soap12";
Importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
CodeNamespace nameSpace = new CodeNamespace(_Namespace);
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(nameSpace);
ServiceDescriptionImportWarnings warnings = Importer.Import(nameSpace, ccu);
if (warnings == 0)
{
StringWriter sw = new StringWriter(System.Globalization.CultureInfo.CurrentCulture);
Microsoft.CSharp.CSharpCodeProvider prov = new Microsoft.CSharp.CSharpCodeProvider();
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BlankLinesBetweenMembers = false;
options.BracingStyle = "C";
prov.GenerateCodeFromNamespace(nameSpace, sw, options);
_ProxySource = sw.ToString();
sw.Close();
}
I don't have the code right now but I know this can be done, in fact in a former company I have worked we did have a generic web service client developed in house.
have a lock here:
Generic Web Service Proxy

Categories

Resources