Consuming a WSDL/Web service in C#/VisualStudio 2015 - c#

While there are many other topics that provide great information on the topic posted here already, I've not yet been able to find the answer to my dilemma.
While I'm somewhat competent with PowerShell, I am completely new with C#/VisualStudio. I have some PowerShell code that consumes a Web service that works perfectly well:
function Modify-SPMLObject() {
param(
[string]$Uri
, [string]$ObjectDN
, [PSCredential]$Creds
, [hashtable]$Attributes
)
$MyService = New-WebServiceProxy -Uri $Uri -Credential $Creds
$Type = $MyService.GetType().Namespace
$ModifyRequest = New-Object -TypeName ($Type + ".CModifyRequest")
$CPSOID = New-Object -TypeName ($Type + ".CPSOID")
$CPSOID.ID = $ObjectDN
$ModifyRequest.psoID = $CPSOID
$Modifications = #()
foreach ($Attribute in $Attributes.Keys) {
$Modification = New-Object -TypeName ($Type + ".modification")
$Modification.Name = $Attribute
$Modification.Value = $Attributes.$Attribute
$Modification.Operation = "replace"
$Modifications += $Modification
}
$ModifyRequest.modification = $Modifications
$MyService.modify($ModifyRequest)
}
My challenge is converting this to C# in VisualStudio. In lieu of the call to New-WebServiceProxy, I've included a reference in my project to the Web service. The reference is named MyService. Hence, the code I've created thus far:
var ModifyRequest = new MyService.CModifyRequest();
var CPSOID = new MyService.CPSOID();
CPSOID.ID = "a hard-coded value for now";
ModifyRequest.psoID = CPSOID;
var modifications = new MyService.modification[1];
var modification = new MyService.modification();
modification.name = "another hard-coded value for the moment";
modification.operation = "replace";
modification.value = new string[1] { "This is a test" };
modifications[0] = modification;
ModifyRequest.modification = modifications;
The one thing that I haven't been able to figure out, however, is how, in C#, to accomplish the task that the PowerShell version accomplishes thus:
$MyService.modify($ModifyRequest)
In VS, if I try to call:
MyService.modify(ModifyRequest);
I get the message
Error CS0234 The type or namespace name 'modify' does not exist in the namespace 'WebApplication2.MyService' (are you missing an assembly reference?)
Any tips are most appreciated!
EDIT: Found the solution. In answer to LachlanB, typing "MyService" provided a list of methods and classes - but not the modify operation that I was seeking and defined in the WSDL thus:
<wsdl:operation name="modify">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Changes the specified object on the target.</wsdl:documentation>
<wsdl:input message="tns:modifySoapIn"/>
<wsdl:output message="tns:modifySoapOut"/>
</wsdl:operation>
What I needed to include was, first, the reference:
using WebApplication2.MyService;
With that, I could then call:
MyApplicationClassName webService = new MyApplicationClassName();
CModifyResponse response = webService.modify(ModifyRequest);
where "MyApplicationClassName" was automatically generated as was listed in References.cs in the following statement:
public partial class MyApplicationClassName : System.Web.Services.Protocols.SoapHttpClientProtocol {
Thanks to those that tried to help!

Related

Get all methods from C# source code

I am looking forward to get all method names used in C# using following code:
CompilerParameters parameters = new CompilerParameters()
{
GenerateExecutable = false,
GenerateInMemory = true
};
var provider = new CSharpCodeProvider();
foreach (string path_file in files)
{
string source = File.ReadAllText(path_file);
Console.Out.WriteLine(source);
CompilerResults results = provider.CompileAssemblyFromSource(parameters, source);
if (results.Errors.HasErrors)
{
foreach (var error in results.Errors)
Console.Out.WriteLine(error.ToString());
return;
}
}
I am trying to read the source code in a variable source and passing this in CompileAssemblyFromSource method of CSharpCodeProvider class.
I am getting the following error under result variable.
c:\Users\username\AppData\Local\Temp\2rdqotiv.0.cs(3,14) : error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly reference?).
Can anyone please help me to solve this error? I am using MVS 15.
You have to add the referenced assemblies, for example:
parameters.ReferencedAssemblies.Add(typeof(Enumerable).Assembly.Location);
You can also add assemblies manually, as follows:
string exDir = $#"C:\WINDOWS\Microsoft.NET\Framework\v{ver}";
parameters.CompilerOptions = $"/lib:{exDir}";
And BTW, you could also use CompileAssemblyFromFile instead of having to open the files manually.

How to fix ambiguous reference errors?

I have a web app that allows importing of contacts from Hotmail, Yahoo and GMail. I finally have it almost completed but since I added the importing of GMail, I am getting ambiguous reference errors and I am unsure how to fix them without breaking any code.
Here is a screen shot of the errors:
Try to use unique class names as much as possible. This will be the better solution in the end.
Write the entire namespace when referencing
OAuth.OAuthBase a = new ...;
Google.GData.Client.OAuthBase b = new ...;
Make an using alias for one or both:
using n2 = OAuth;
using Google.GData.Client;
n2.OAuthBase a = new ...; // referenced using namespace
OAuthBase b = new ...; // referenced through existing `using`
you can try something like this..
using GoogleOAuthBase = Google.GData.Client.OAuthBase;
namespace abc
{
public class Program
{
//make sure this Google.GData.Client.OAuthBase is instansiateable
var googleBase = new GoogleOAuthBase();
}
}
you can try entire name space as well.
var googleBase = new Google.GData.Client.OAuthBase();

namespace name soapcontext could not be found

I am building a form application that makes a call to a third party web service, but keep getting a "namespace name soapcontext could not be found" error.
I already added a web reference that points to the wsdl for the web service. Here is what I have:
private void btnGetInfo_Click(object sender, EventArgs e)
{
QTWebSvcsService svc = new qtref.QTWebSvcsService();
// The getVehicleInformation method accepts an AssetIdentifier and returns a
// VehicleInfo object. Instantiate them both.
qtref.AssetIdentifier ai = new qtref.AssetIdentifier();
qtref.VehicleInfo vi = new qtref.VehicleInfo();
// Replace these strings with valid company name, user name and password
string sUsername = "[usernasme]";
string sCompanyname = "[company]";
string sIdentity = sUsername + "#" + sCompanyname;
string sPassword = "[password]";
//This is where it fails
SoapContext requestContext = RequestSoapContext.Current;
}
Here is the exact error:
Error 1 The type or namespace name 'SoapContext' could not be found (are you missing a using directive or an assembly reference?) C:\Users\Sophia Carter\Documents\Visual Studio 2010\Projects\DemoGetVehInf\DemoGetVehInf\Form1.cs 45 13 DemoGetVehInf
Based on the error, it looks like you need a using statement to include the namespace that contains SoapContext.
I don't know what namespace this would be but at the top of your code you will place something like:
using SoapContextNamespace;
I personally use Visual Studio with ReSharper. This combination of tools detects this error and offers a way to correct it with selecting something from the context menu when you right click. Depending on your tool set, you may find this or a similar option.

Runtime compilation generates a file that can't be removed

I have this console type thing that accepts a line of C# code, wraps it up in some surrounding code and compiles it into an assembly. Then, I invoke the method from that assembly, output the result and that's it.
The problem is, the assembly needs to have a name so I can set it as a friend assembly so it could access the non-public classes. I named it "console".
Everything worked as expected but the problem is that I can't run a second script after one has finished because the file named "console" already exists in the directory and can't be overwritten.
I've tried Disposing of everything that has a Dispose method. I've tried manually deleting the file with File.Delete. Nothing helped.
So here's the code I'm using. I hope someone can help me.
CSharpCodeProvider provider = new CSharpCodeProvider();
var param = new CompilerParameters();
param.GenerateInMemory = false;
param.GenerateExecutable = false;
param.OutputAssembly = "console";
param.ReferencedAssemblies.Add("System.dll");
param.ReferencedAssemblies.Add("System.Core.dll");
param.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
var results = provider.CompileAssemblyFromSource(param,
#"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace FireflyGL
{
class DebugConsole
{
static void Run(StringWriter writer)
{
var stdOut = Console.Out;
Console.SetOut(writer);
" + input.Text + #"
Console.SetOut(stdOut);
}
}
}");
if (results.Errors.HasErrors)
{
for (int i = 0; i < results.Errors.Count; ++i)
{
PushText(results.Errors[i].ErrorText);
}
}
else
{
try
{
var writter = new StringWriter();
results.CompiledAssembly.GetType("FireflyGL.DebugConsole").GetMethod("Run", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[] { writter });
PushText(writter.ToString());
history.Add(input.Text);
currentHistory = history.Count;
input.Text = "";
writter.Dispose();
}
catch (Exception)
{
}
}
provider.Dispose();
File.Delete(results.CompiledAssembly.Location);
You have to unload the assembly to get rid of all the references. Unfortunately, you can't do that. You can however unload an AppDomain and provided you reference your assembly in that AppDomain, it will be unloaded as well.
If you don't care about creating a memory leak, you could also just create unique names for your assembly (console1, console2 etc.)...

Migrate Microsoft.Build.BuildEngine.Engine to Microsoft.Build.Evaluation.ProjectCollection

after Microsoft marked the BuildEngine.Engine and BuildEngine.Project as obsolete i have tried to use the new proposal from Microsoft how you can see it underneath. But i have no idea where i can integrate the xmlprojectfile. Is here someone who knows the solution of this problem?
The XML project file content
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectToBuild Include ="myproject.csproj" />
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="#(ProjectToBuild)"
Properties="Configuration=Debug" StopOnFirstFailure="true" />
</Target>
</Project>
The old and working version (but obsolete)
Microsoft.Build.BuildEngine.Engine engine = new Microsoft.Build.BuildEngine.Engine();
engine.DefaultToolsVersion = "4.0";
engine.RegisterLogger(new ConsoleLogger());
Microsoft.Build.BuildEngine.Project project = new Microsoft.Build.BuildEngine.Project(engine);
project.Load(xmlprojectfile);
if (!project.Build())
{
Console.ReadLine();
}
The new not working verison
Microsoft.Build.Evaluation.ProjectCollection collection = new Microsoft.Build.Evaluation.ProjectCollection();
collection.DefaultToolsVersion = "4.0";
collection.RegisterLogger(new ConsoleLogger());
Microsoft.Build.Evaluation.Project project = new Microsoft.Build.Evaluation.Project(collection);
if (!project.Build())
{
Console.ReadLine();
}
You also need to create a Microsoft.Build.Execution.BuildRequestData object containing the XML project file and a dictionary of std properties like Configuration and Platform. Then you create a Microsoft.Build.Execution.BuildParameters object containing your ProjectCollection object from your code snippet and pass that off to the default Microsoft.Build.Execution.BuildManager.
powershell pseudo code:
#set build properties
$props = new-object "System.Collections.Generic.Dictionary``2[[System.String],[System.String]]"
$props.Add("Configuration",$config)
$props.Add("Platform",$platform)
#create the projectCollection
$projectCollection = new-object Microsoft.Build.Evaluation.ProjectCollection -argumentList $props,$loggers,"ConfigurationFile,Registry"
$request = new-object Microsoft.Build.Execution.BuildRequestData -argumentlist $project,$props,$null,$targets,$null
#create a BuildParameters object to hold the Project Collection
$parameters = new-object Microsoft.Build.Execution.BuildParameters -argumentlist #($projectCollection)
$parameters.MaxNodeCount = 1
$parameters.Loggers = $projectCollection.Loggers
$parameters.ToolsetDefinitionLocations = "ConfigurationFile,Registry"
$parameters.DefaultToolsVersion = $toolsVersion
#get the build manager and submit a build request with the appropriate parameters
$manager = [Microsoft.Build.Execution.BuildManager]::DefaultBuildManager
$result = $manager.Build($parameters, $request)
You are missing project.Load(xmlprojectfile); line in your migrated code. You have to add xmlprojectfile into projectcollection somehow, I guess.
Instead of creating a new Project with new keyword:
// var project = new Project(collection);
Use this:
var project = collection.LoadProject("myproject.csproj")

Categories

Resources