Options

"Metadata for object... " error when calling web service

rspruitrspruit Member Posts: 25
edited 2010-05-24 in NAV Three Tier
I have a NAV web service. I'm making a client in C# with the ultimate goal to create a class that can cope with all possible web services, to be called from NAV and other C# programs. When I make a web reference, calling the web service goes well. Trying to achieve my ultimate goal, I get the following error:
Metadata for object of type Table with id 11151182 is in a failed state. This is caused by a previous exception:
Could not find a part of the path 'C:\Documents and Settings\All Users\Application Data\Microsoft\Microsoft Dynamics NAV\60\Server\MicrosoftDynamicsNavServer\source\Record\Record11151182.cs'.
at ProductionPlanTest.CDynamicWebServiceCaller.CallWebMethod()
at ProductionPlanTest.CDynamicWebServiceCaller.CallWebMethod(String methodName, Object[] parameters)
at ProductionPlanTest.Program.Main(String[] args)


The class generates code and an assembly from a wsdl supplied by a url or file. Then the function is called from that assembly. I found some other examples of ways to call a web service, but this seems to be the most flexible.

I hope someone can help me out here.

Thanx in advance,

Remco


Here is the code of the client class:
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;

namespace ProductionPlanTest
{
class CDynamicWebServiceCaller
{
private class WebMethodCall
{
public string MethodName;
public System.Reflection.MethodInfo MethodInfo;
public System.Reflection.ParameterInfo [] ParameterInfo;
public object[] ParameterValues;
}

private ServiceDescription _serviceDescription;
private System.Reflection.Assembly _proxyAssembly;
private object _serviceInstance;
private System.Type _assemblyType;
private WebMethodCall _currentWebMethodCall;
private bool _hasWSDL, _useDefaultCredentials, _credentialsSetExplicit;

public CDynamicWebServiceCaller()
{
ServicePointManager.ServerCertificateValidationCallback = SSLCallBack;
}

public bool HasWSDL
{
get
{
return _hasWSDL;
}
}

public bool UseDefaultCredentials
{
get
{
return _useDefaultCredentials;
}
set
{
_credentialsSetExplicit = true;
_useDefaultCredentials = value;
}
}

/// <summary>
/// Get the WSDL definition from a web service call
/// </summary>
/// <param name="uri">URI of the web service</param>
public void GetWSDLFromURI(string uri)
{
if (string.IsNullOrEmpty(uri))
throw new Exception("The uri is not supplied");

var _webrequest = WebRequest.Create(uri);

if (_credentialsSetExplicit)
_webrequest.UseDefaultCredentials = _useDefaultCredentials;

var _stream = _webrequest.GetResponse().GetResponseStream();
_serviceDescription = ServiceDescription.Read(_stream);

this.GenerateProxyClass();
}

/// <summary>
/// Get the WSDL definition from a file
/// </summary>
/// <param name="filename">Full path and file name of the requested WSDL file</param>
public void GetWSDLFromFile(string filename)
{
if (string.IsNullOrEmpty(filename))
throw new Exception("The file name is not supplied");

_serviceDescription = ServiceDescription.Read(filename);

this.GenerateProxyClass();
}

/// <summary>
/// Initializes a new web service method call. Ensure to provide all necessary information before calling CallWebMethod()
/// </summary>
/// <param name="methodName">Name of the methode</param>
public void NewMethodCall(string methodName)
{
CheckWSDL();

_currentWebMethodCall = new WebMethodCall();
_currentWebMethodCall.MethodName = methodName;
_currentWebMethodCall.MethodInfo = _assemblyType.GetMethod(methodName);
_currentWebMethodCall.ParameterInfo = _currentWebMethodCall.MethodInfo.GetParameters();
_currentWebMethodCall.ParameterValues = null;
}

public string CallWebMethodAsString()
{
return CallWebMethod().ToString();
}

public object CallWebMethod()
{
CheckWSDL();

if (_currentWebMethodCall == null)
throw new Exception("Please start a new call with NewMethodCall");

if (_credentialsSetExplicit)
{
var _propertyInfo = _assemblyType.GetProperty("UseDefaultCredentials");
_propertyInfo.SetValue(_serviceInstance, _useDefaultCredentials, null);
}

try
{
return _currentWebMethodCall.MethodInfo.Invoke(_serviceInstance, _currentWebMethodCall.ParameterValues);
}
catch (Exception e)
{
// The failed Invoke throws a general error containing the actual error
if (e.InnerException != null)
throw e.InnerException;
else
throw e;
}
}

public object CallWebMethod(string methodName)
{
CheckWSDL();

_currentWebMethodCall = new WebMethodCall();
_currentWebMethodCall.MethodName = methodName;
_currentWebMethodCall.MethodInfo = _assemblyType.GetMethod(methodName);
_currentWebMethodCall.ParameterInfo = _currentWebMethodCall.MethodInfo.GetParameters();
_currentWebMethodCall.ParameterValues = null;

return CallWebMethod();
}

public object CallWebMethod(string methodName, object [] parameters)
{
CheckWSDL();

_currentWebMethodCall = new WebMethodCall();
_currentWebMethodCall.MethodName = methodName;
_currentWebMethodCall.MethodInfo = _assemblyType.GetMethod(methodName);
_currentWebMethodCall.ParameterInfo = _currentWebMethodCall.MethodInfo.GetParameters();
_currentWebMethodCall.ParameterValues = parameters;

return CallWebMethod();
}

private void CheckWSDL()
{
if (!_hasWSDL)
throw new Exception("No WSDL specification has been loaded");
}

private void GenerateProxyClass()
{
// Service importer
var _serviceImporter = new ServiceDescriptionImporter();
_serviceImporter.AddServiceDescription(_serviceDescription, null, null);
_serviceImporter.ProtocolName = "Soap";
_serviceImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;

// Import
var _codeNameSpace = new CodeNamespace();
var _codeCompileUnit = new CodeCompileUnit();
_codeCompileUnit.Namespaces.Add(_codeNameSpace);
var _warnings = _serviceImporter.Import(_codeNameSpace, _codeCompileUnit);

// Check import
if (_warnings == ServiceDescriptionImportWarnings.NoCodeGenerated || _warnings == ServiceDescriptionImportWarnings.NoMethodsGenerated)
throw new Exception(string.Format("The following error occurred while importing the WSDL: {0}", _warnings.ToString()));

// Genereate code
using (var _stringWriter = new StringWriter(CultureInfo.CurrentCulture))
{
var _codeProvider = CodeDomProvider.CreateProvider("CSharp");
_codeProvider.GenerateCodeFromNamespace(_codeNameSpace, _stringWriter, null);

// Compiler parameters
var _params = new CompilerParameters(new string[] { "System.dll", "System.Xml.dll", "System.Web.Services.dll", "System.Data.dll" });
_params.GenerateExecutable = false;
_params.GenerateInMemory = true;
_params.TreatWarningsAsErrors = false;
_params.WarningLevel = 4;
_params.IncludeDebugInformation = false;
var _compilerResults = _codeProvider.CompileAssemblyFromSource(_params, _stringWriter.ToString());
_proxyAssembly = _compilerResults.CompiledAssembly;
// Create instance
_assemblyType = _proxyAssembly.GetType(_serviceDescription.Services[0].Name);
_serviceInstance = Activator.CreateInstance(_assemblyType);
}

_hasWSDL = true;
}

private static bool SSLCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
}


And the test program:
Using System;
using System.IO;
namespace ProductionPlanTest
{
class Program
{
static void Main(string[] args)
{
try
{
CDynamicWebServiceCaller ws = new CDynamicWebServiceCaller();
ws.UseDefaultCredentials = true;

if (args.Length > 0)
Console.WriteLine("Argument: {0}", args[0]);

if (args.Length > 0)
ws.GetWSDLFromURI(@"http://webserver:7047/DynamicsNAV/WS/webserver_BV/Codeunit/TL_CTS_Communication");
else if (args.Length > 0 && File.Exists(args[0]))
ws.GetWSDLFromFile(args[0]);
else
ws.GetWSDLFromFile(@C:\Indigo Solutions\ISAL\TL_CTS_Communication.xml);

Console.WriteLine("Call 1 {0}", ws.CallWebMethod("UpdateContainerAction", new object[] { "3017", "TL", "OPPOTTEN", "OPPOTTEN", "GROOT", "PV100003", 123 }));
Console.WriteLine("Call 2 {0}", ws.CallWebMethod("UpdateContainerAction", new object[] { "3017", "TL", "OPPOTTEN", "OPPOTTEN", "KLEIN", "PV100003", 123 }));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
finally
{
Console.ReadLine();
}
}
}
}


And, yes this is the last, (part of) the code generated by the class (dump from the stringwriter):
using System.Diagnostics;
using System.Web.Services;
using System.ComponentModel;
using System.Web.Services.Protocols;
using System;
using System.Xml.Serialization;


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("ProductionPlanTest", "1.0.0.0")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(
Name = "TL_CTS_Communication_Binding",
Namespace = "urn:microsoft-dynamics-schemas/codeunit/TL_CTS_Communication")]
public partial class TL_CTS_Communication : System.Web.Services.Protocols.SoapHttpClientProtocol
{

/// <remarks/>
public TL_CTS_Communication()
{
this.Url = "http://terlaakdb01:7047/DynamicsNAV/WS/Ter_Laak_Orchideeën_BV/Codeunit/TL_CTS_Communication";
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"urn:microsoft-dynamics-schemas/codeunit/TL_CTS_Communication:UpdateContainerAction",
RequestNamespace = "urn:microsoft-dynamics-schemas/codeunit/TL_CTS_Communication",
ResponseElementName = "UpdateContainerAction_Result",
ResponseNamespace = "urn:microsoft-dynamics-schemas/codeunit/TL_CTS_Communication",
Use = System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return_value")]
public bool UpdateContainerAction(string containerCode, string locationCode, string growthAction, string growthPhase, string sortingCode, string jobNo, int quantity)
{
object[] results = this.Invoke("UpdateContainerAction", new object[] {
containerCode,
locationCode,
growthAction,
growthPhase,
sortingCode,
jobNo,
quantity});
return ((bool)(results[0]));
}
}

Comments

  • Options
    chrisgrill3chrisgrill3 Member Posts: 18
    I received a similar error when working with web services. A re-compile of the table mentioned in the error fixed the problem.
  • Options
    rspruitrspruit Member Posts: 25
    I received a similar error when working with web services. A re-compile of the table mentioned in the error fixed the problem.

    Thanks for your reply. I tried it and the original error message is exchanged for another, but this is at an earlier part of the program (WSDLfromURI) that before the compilation did not go wrong. I get compilation errors (NAV client crashes during compilation). So I will try to get the errors fixed before trying the web service again.

    I'll let you know.
Sign In or Register to comment.