dynamic binding of web service URI - c#

I have a list of servers, all exposing the same web service interface, that I need to call from my code.
i.e.
https://server1/service.asmx
https://server2/service.asmx
https://server3/service.asmx
My code needs to get this list of servers and invoke the same function on all of them.
I added a web references to this service, and I use "Dynamic" URL behavior. This is supposed to let me create an instance of the server proxy object, set the URI property at runtime, and then invoke the web methods, right?
But it seems the code generated by VS assumes the URI will come from the application's config file, which isn't the case for this app.
public SharpEyeWebService() {
this.Url = global::Company.DotNet.MyProject.Properties.Settings.Default.MyWebService;
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
}
else {
this.useDefaultCredentialsSetExplicitly = true;
}
}
Is it safe to ignore the default URL the constructor uses and employ the approach I described above?

You can always set the Url, so yes this is safe. The "dynamic" you describe only influences the default Url: whether it hard-coded or comes from config.
So indeed, this is moot if you are supplying this yourself.
The awkward bit here is that it also sets UseDefaultCredentials based on what it finds - so it would be worth setting this manually so you know the value.

Related

Expect Continue Inconsistencies on Different Environments

I have some troubles with the header Expect 100-Continue on a DELETE method inside a .NET 4.5 application. The client in provides also a small content body inside the call.
The official microsoft documentation seems to imply that this header is passed by default only in PUT and POST calls with a non-empty content, but it does not say nothing about DELETE. Does anyone know if this configuration also applies to DELETE?
I'm experiencing different behaviour on different environment of my web application in particular I have some environments in which the header is never passed (even in PUT and POST) without any clue about it being deactivated.
In order to interact with this option I know only four ways:
Via ServicePointManager through
System.Net.ServicePointManager.Expect100Continue = false;
Editing client options
var c = new HttpClient();
c.DefaultRequestHeaders.ExpectContinue = false;
Adding or removing it manually on HttpWebRequest with AddHeader/Remove
Using the following property on Web.Config
<system.net>
<settings>
<servicePointManager expect100Continue="false"/>
</settings>
</system.net>
Unfortunately none of these seems to be my case. Are there any other ways to mess with this option?
Just managed to find out the solution for this issue. I found out that some of my environment use the couchbase client to handle distributed cache, differently from IIS couchbase internally sets Expect100Continue to true but it does that in the following way.
namespace Couchbase.Configuration.Client
{
public class ClientConfiguration {
//...
public ClientConfiguration()
{
//...
this.Expect100Continue = false;
}
//--
public bool Expect100Continue
{
get
{
return ServicePointManager.Expect100Continue;
}
set
{
ServicePointManager.Expect100Continue = value;
}
}
}
}
they use change this property using the static ServicePointManager method and this means that every following instantiated client will change their behaviour.
My version of Couchbase Client is 2.1.4.0

Declare generic Service Reference client object for scoping issue

I have this in my web.config
If this value is live, then I want to call the live web service, and if it's not, then I want to call the test web service.
In my code I want to do something like this:
if (System.Configuration.ConfigurationManager.AppSettings["runMode"] == "live")
{
var client = new CallStatusAvailability.ServiceReference1
.StatusAvailabilityRoomsClient();
}
else
{
var client = new CallStatusAvailability.StatusAvailabilityRooms
.StatusAvailabilityRoomsClient();
}
using (client)
{
...... lots of logic
}
The problem is that client is out of scope. I would like to be able to declare client before the if statement, but not sure what I can define it as?
I could put the using statement within the if or the else statement, but I would then have to duplicate all the logic in both.
At first I tried to create a function that could be called from the if and the else, and pass in client, but then I face the same issue of what type to declare the input client variable as, as an input to the function.
I would suggest that you not add both service references to your project, but a single service reference (probably to the test service) and vary the connection parameters using configuration transforms. You would do this by setting your base web.config up to connect to the test service, then add a transform in web.Release.config to change the binding when deployed using the Release target. This will simplify your logic to the point where you won't need the if-else construct and allow you to create the client within a using statement.
Your issue is that var is declaring a variable. If you need to use a variable in this way you can't use var as it need to be declared at a higher level of scope. Just move your declaration to the containing block. This assumes the service references are using the same type; if not, you need to fix that first or use dynamic if they are semantically identical. You also can't use a using in this context and must use try catch finally.
To use the same types I would suggest generating the proxy using the channel factory or using svcutil so that your types are the same for the different service references.
CallStatusAvailability.ServiceReference1.StatusAvailabilityRoomsClient client = null;
try
{
if (System.Configuration.ConfigurationManager.AppSettings["runMode"] == "live")
{
client = new CallStatusAvailability.ServiceReference1.StatusAvailabilityRoomsClient();
}
else
{
client = new CallStatusAvailability.StatusAvailabilityRooms.StatusAvailabilityRoomsClient();
}
}
catch(..){}
finally
{
client.Dispose();
}

How to choose a WCF service to connect to?

I have two separate servers with identical WCF services (let's say, WS1 and WS2) and a C# Mobile CF 2.0 project that need to access both of the services.
Can I do something like this on the C# CF2.0 project?
(...)
if (someCondition == true)
{
WS1 aux = new WS1();
}
else
{
WS2 aux = new WS2();
}
aux.service(parameter1);
(...)
note that I want to have the same variable name, independent of which server I'll access. The problem is: I don't know how to declare it outside the conditional statements and when I just declare it inside the conditional statements they're declared as local variables and I don't know how to make the variable public or global.
Any thoughts or help, please?
Since the WCF Service is exactly the same, just running on different servers, then from your client project simply add a service reference to one of them (WS1 for example). This will generate the client proxy for you. Perhaps give it a generic name too, like "serviceX" (replacing X with something appropriate for your application).
Then, in your client config file, copy the client endpoint it created and add another endpoint with the only difference being the address and the endpoint name. Maybe you want to set the endpoint name property on each endpoint to be "WS1" and "WS2" respectively.
Then, in your code, you should be able to do something like this:
(...)
serviceXClient aux = null;
if (someCondition == true)
{
aux = new serviceXClient("WS1");
}
else
{
aux = new serviceXClient("WS2");
}
aux.service(parameter1);
(...)
If you're using .Net 4.0 or higher you could use dynamic typing.
http://msdn.microsoft.com/en-us/library/dd264736.aspx

How can I get web service method being called by HttpContext?

I have web service with 40 different web methods.
Can I get in my web service the Method that the request sent from using HttpContext?
I need it because I have abstract general command that all the methods activate and I have access only to HttpContext.
Thanks!
If I understand correct your question you can use PathInfo property of the HttpRequest:
string methodName = HttpContext.Current.Request.PathInfo;
The string methodName will be the method name with the slash prefix (/): "/MyWebMethod".
You probably need:
HttpContext.Current
But be sure you've the ASPX compatibility mode turned on, otherwise you'll not be able to access that property
You can also save the name of the function into the Items array like this:
void myServiceMethod()
{
HttpContext.Current.Items["MethodName"] = "myServiceMethod";
// ...
// here comes your method implementation
}
and then you can anywhere read the HttpContext.Current.Items["MethodName"]
colection HttpContext.Current.Items is valid always only for current request, so you can use it as a storage for any request related information.
When the request is responded, it's garbage.

Reporting Services Web Service, C# .NET code reuse

I'm building a custom front-end for a collection of reporting services servers. I'm adding the ReportingServices2005 web reference to my project using;
http://server/ReportServer_InstanceName/ReportService2005.asmx?wsdl
At the moment my approach is to add this reference for each server, however I'm then struggling with the code reuse aspect. The reporting services classes are then different namespaces.
I'd like to have a method as below;
public string ListReports(Server1WebService.ReportingService2005 service) {
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
service.Server1WebService.CatalogItem[] children = service.ListChildren("/", true);
string list = String.Empty;
foreach (Server1WebService.CatalogItem i in children) {
if (!i.Hidden)
list += i.Name + "</br>";
}
return list;
}
To make this method reusable I need to know how to refactor this so that any instance of the ReportingService2005 class can be passed regardless of the namespace. At the moment I have to specify Server1WebService for all references to ReportingService2005 and CatalogItem.
Provided that all of the SSRS instances are the same version, You should be able to set the URL property on the proxy object:
Server1WebService server.url = new uri ("http://server/ReportServer_InstanceName/ReportService2005.asmx?wsdl"));
If you have multiple versions to deal with, you may need to provide some type of factory object that can correctly instantiate the correct version.
Hope this helps

Categories

Resources