Description
I've been attempting to use a custom DLL in Unity. I've confirmed the DLL runs correctly outside Unity.
The DLL imports into Unity and when I refer to it in my scripts, I get no compiler errors. However, trying to run a function from the DLL at runtime gives this error:
InvalidOperationException: Client endpoint configuration '*' was not found in 0 endpoints.
System.ServiceModel.ChannelFactory.ApplyConfiguration (System.String endpointConfig)
System.ServiceModel.ChannelFactory.InitializeEndpoint (System.String endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
System.ServiceModel.ChannelFactory`1[DNDUtility.ContentVaultServiceTest.IContentVaultService]..ctor (System.String endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
System.ServiceModel.ClientBase`1[TChannel].Initialize (System.ServiceModel.InstanceContext instance, System.String endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
System.ServiceModel.ClientBase`1[TChannel]..ctor (System.ServiceModel.InstanceContext instance, System.String endpointConfigurationName)
System.ServiceModel.ClientBase`1[TChannel]..ctor (System.ServiceModel.InstanceContext instance)
System.ServiceModel.ClientBase`1[TChannel]..ctor ()
DNDUtility.ContentVaultServiceTest.ContentVaultServiceClient..ctor ()
DNDUtility.DataManager..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for DNDUtility.DataManager
TestStuff.OnGUI () (at Assets/TestStuff.cs:39)
I've tried compiling the DLL with .NET 4, 4.5, 3.5, and 2. (I can provide the DLL file if needed.)
What causes this?
Code listings
DLL code
using System;
using System.Xml.Linq;
using System.Security.Cryptography;
using System.Text;
using System.IO;
namespace DNDUtility
{
using ContentVaultServiceTest;
public class DataManager
{
static ContentVaultServiceClient contentClient = new ContentVaultServiceClient();
public static bool Login(string user, string pass)
{
return contentClient.Login(user,
SimpleEncrypt(pass, user));
}
public static string[] GetChars()
{
ContentInfo[] content = contentClient.GetAvailableContent(0);
string[] chars = new string[content.Length];
for (int i = 0; i < content.Length; i++)
{
XDocument doc = XDocument.Parse(content[i].CommittedContent.Details.ToString());
var name = doc.Element("CharacterDetails").Element("Name").Value;
chars[i] = string.Format("{0} : {1}", i, name);
}
return chars;
}
public static void GetData()
{
ContentInfo[] content = contentClient.GetAvailableContent(0);
DataWithVersion data = contentClient.GetData(
new ContentIdentifier() { ContentID = content[0].CommittedContent.Identifier.ContentID },
null);
RawContentBlob blob = data.Data as RawContentBlob;
String charFile = new UTF8Encoding().GetString(blob.RawData, 0, blob.RawData.Length);
XDocument doc = XDocument.Parse(charFile);
doc.Save("d:\Users\Tim Williams\Desktop\Work Documents\TerabyteTim\DND App\ContentVault\ConsoleApplication1\contentdoc.xml");
}
public static byte[] SimpleEncrypt(string value, string key)
{
byte[] buffer2;
ICryptoTransform transform = GetSimpleAlgorithm(key).CreateEncryptor();
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
stream2.Write(bytes, 0, bytes.Length);
stream2.Flush();
stream2.FlushFinalBlock();
stream.Position = 0L;
buffer2 = stream.ToArray();
}
}
return buffer2;
}
static SymmetricAlgorithm GetSimpleAlgorithm(string key)
{
AesManaged aes = new AesManaged();
byte[] source = new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(key));
byte[] take = new byte[aes.BlockSize / 8];
for (int i = 0; i < aes.BlockSize / 8; i++)
{
take[i] = source[i];
}
return new AesManaged { Key = source, IV = take };
}
}}
Unity C# script
This script tries to access the DLL.
using System;
using System.Runtime.InteropServices;
using DNDUtility;
using UnityEngine;
using System.Collections;
public class TestStuff : MonoBehaviour
{
void OnGUI()
{
if (GUI.Button(new Rect(0, 0, 100, 100), "Login"))
{
Debug.Log(DataManager.Login("username", "password"));
}
if (GUI.Button(new Rect(125, 0, 100, 100), "Get Characters"))
{
string[] chars = DataManager.GetChars();
for (int i = 0; i < chars.Length; i++)
{
Debug.Log(chars[i]);
}
}
}
}
You can find the ContentVaultServiceTest at this Pastebin.
DNDUtility App.config
code
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="CustomBinding_IContentVaultService" maxReceivedMessageSize="200000000"
allowCookies="true">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://ioun.wizards.com/ContentVault.svc"
binding="wsHttpBinding" bindingConfiguration="CustomBinding_IContentVaultService"
contract="ContentService.IContentVaultService" name="CustomBinding_IContentVaultService" />
</client>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
I've tried multiple different settings for the contentClient
:
static string endpointConfigurationName = "CustomBinding_IContentVaultService";
static EndpointAddress remoteAddress = new EndpointAddress("http://ioun.wizards.com/ContentVault.svc");
static ContentVaultServiceClient contentClient = new ContentVaultServiceClient(endpointConfigurationName, remoteAddress);
static WSHttpBinding customBinding = new WSHttpBinding() { AllowCookies = true, MaxReceivedMessageSize = 200000000, Name = "CustomBinding_IContentVaultService" };
static EndpointAddress remoteAddress = new EndpointAddress("http://ioun.wizards.com/ContentVault.svc");
static ContentVaultServiceClient contentClient = new ContentVaultServiceClient(customBinding, remoteAddress);
When used in an external project without an App.config
(using the first solution) I get this error:
Exception:Thrown: "Could not find endpoint element with name 'CustomBinding_IContentVaultService' and contract 'ContentService.IContentVaultService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element." (System.InvalidOperationException)
A System.InvalidOperationException was thrown: "Could not find endpoint element with name 'CustomBinding_IContentVaultService' and contract 'ContentService.IContentVaultService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element."
Time: 4/13/2014 2:07:22 PM
Thread:<No Name>[7520]
Using the second solution, I get:
Exception:Caught: "Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint. " (System.ServiceModel.Security.SecurityNegotiationException)
A System.ServiceModel.Security.SecurityNegotiationException was caught: "Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint. "
Time: 4/13/2014 2:35:38 PM
Thread:<No Name>[1356]
What should I set the EndpointIdentity
to?