browse by category or date

Windows Communication Foundation (WCF) service exposes contracts to its clients. Contract here refers to the platform-neutral and standard way of describing what is available/can be done in the service. Below are the types of contracts:

1. Service contracts

It describes what operations the client can call/perform on the service.

[ServiceContract]
interface ILibrary
{
   [OperationContract]
   bool Borrow(Book arg1, User arg2);

   [OperationContract]
   bool Return(Book arg1, User arg2);
}

2. Data contracts

It defines the data-type which will be passed, to and from the service. Built in types (int, string) will be implicitly defined. But complex/custom data type must be explicitly defined. The custom/complex data type must be serializable.

[DataContract]
struct Book
{
   [DataMember]
   public int Id;

   [DataMember]
   public string Title;

   [DataMember]
   public string ISBN;
}

3. Fault contracts

It defines what errors will be raised by the service, how it handles and propagates the error to its clients. Fault contract can only be declared on operation contract which returns value.

[ServiceContract]
interface ILibrary
{
   [OperationContract]
   [FaultContract(typeof(InvalidArgumentException))]
   bool Borrow(Book arg1, User arg2);

   [OperationContract]
   [FaultContract(typeof(InvalidArgumentException))]
   bool Return(Book arg1, User arg2);
}

4. Message contracts

A message is the packaged information which is sent to/from service. The package’s outer layer is the envelope. Inside the envelope, there is a header, and a body (similar to data defined by data contracts). A message contract allows the service to interact directly with messages (e.g. accessing information defined in the header)

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public Operation operation;  
  [MessageHeader] public DateTime transactionDate;  
  [MessageBodyMember] private Account sourceAccount;  
  [MessageBodyMember] private Account targetAccount;  
  [MessageBodyMember] public int amount;  
}

Which will generate the following SOAP envelope:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">  
  <s:Header>  
    <h:operation xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">Deposit</h:operation>  
    <h:transactionDate xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">2012-02-16T16:10:00</h:transactionDate>  
  </s:Header>  
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
    <BankingTransaction xmlns="http://tempuri.org/">  
      <amount>0</amount>  
      <sourceAccount xsi:nil="true"/>  
      <targetAccount xsi:nil="true"/>  
    </BankingTransaction>  
  </s:Body>  
</s:Envelope> 

Message contracts sample is taken from HERE.

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

One of the reason of my interest with Unity Framework is that its scripting is done in C#. The other reason is the ability to export the game to WebGL. This way we can create a game, and serve it through browser.

I have exported the incomplete game I created in my last post. Here’s the output folder:

Most of the files are the usual web resources: HTML, CSS, images and javascript. Except the content of build folder:

Since I’m not sure what are these .br files for, I take a peek using Notepad++:

Based on above, these .br files are brotli-compressed resources. Thankfully, I have enabled brotli compression on this blog. So I would expect that this blog should be able to serve the game without trouble. After uploading all the files and folders to https://sodeve.net/unity/index.html, I tested it in Firefox.

The game loading screen loads, but stuck at 90%:

This is where my nightmare starts as I encountered errors after errors.

Uncaught ReferenceError: unityFramework is not defined

Apparently the browser was unable to load build.framework.js.br. Looking at Network tab of Developer Tools:

NGINX is returning the incorrect Content-Type. It should application/x-javascript. From the response header, I can’t find Content-Encoding: br.

To fix this, we need to ensure NGINX return the correct content-type and content-encoding:

	location ~* /unity/.*\.js\.br$ {
		brotli off;
		types {}
		default_type application/x-javascript;
		add_header Content-Encoding br;	
	}

Yayy progress, now I have new error message 😀

wasm streaming compile failed: TypeError: WebAssembly: Response has unsupported MIME type ‘application/octet-stream’ expected ‘application/wasm’

Again, the solution is by changing how NGINX gives response:

	location ~* /unity/.*\.wasm\.br$ {
		brotli off;
		types {}
		default_type application/wasm;
		add_header Content-Encoding br; 
	}

Another progress, another new error message.

Uncaught (in promise) RangeError: too many arguments provided for a function call

Because it’s difficult to see the source of exception, I switched to Chrome because it has the ability to format the source code. Thanks to Chrome, I can identify where the exception was thrown (build.loader.js):

function(e) {
	var t = new DataView(e.buffer,e.byteOffset,e.byteLength)
	  , r = 0
	  , n = "UnityWebData1.0\0";
	if (!String.fromCharCode.apply(null, e.subarray(r, r + n.length)) == n)
		throw "unknown data format";
	r += n.length;
	var o = t.getUint32(r, !0);
	for (r += 4; r < o; ) {
		var a = t.getUint32(r, !0);
		r += 4;
		var s = t.getUint32(r, !0);
		r += 4;
		var i = t.getUint32(r, !0);
		r += 4;
		var d = String.fromCharCode.apply(null, e.subarray(r, r + i)); //Exception source
		r += i;
		for (var u = 0, c = d.indexOf("/", u) + 1; c > 0; u = c,
		c = d.indexOf("/", u) + 1)
			l.FS_createPath(d.substring(0, u), d.substring(u, c - 1), !0, !0);
		l.FS_createDataFile(d, null, e.subarray(a, a + s), !0, !0, !0)
	}
	l.removeRunDependency("dataUrl")
}

To help me debug, I format build.loader.js and made small change, put a breakpoint:

It seems we are trying to pass 795818 parameters to a function. No wonder we have “too many arguments provided for a function call” error. Since the offending line is simply converting array of uint to string, let’s rewrite it:

var zzz = e.subarray(r, r + i);
var d = ""; //String.fromCharCode.apply(null, zzz);
var ctr = 0,
	len = zzz.length;
while (ctr < len) {
	d += String.fromCharCode(zzz[ctr++]);
}
r += i;

Too bad, above code is very slow. Iterating 795818 items is painfully slow. Let's try to pass the maximum number parameters. Based on the documentation, we can pass at most 65535 (0xFFFF).

Syntax

String.fromCharCode(num1)
String.fromCharCode(num1, num2)
String.fromCharCode(num1, num2, ..., numN)

Parameters

num1, ..., numN
A sequence of numbers that are UTF-16 code units. The range is between 0 and 65535 (0xFFFF). Numbers greater than 0xFFFF are truncated. No validity checks are performed.

With this information, let's modify the code:

var zzz = e.subarray(r, r + i);
var d = ""; //String.fromCharCode.apply(null, zzz);
var ctr = 0,
	maxParamCount = 64000,
	len = zzz.length;
while (ctr < len) {
	var paramCount = ctr + maxParamCount >= len ? len - ctr : maxParamCount;
	d += String.fromCharCode.apply(null, zzz.subarray(r + ctr, paramCount));
	ctr += paramCount;
}
r += i;

It's a progress! A new error message discovered.

Uncaught (in promise) RangeError: offset is outside the bounds of the DataView

Last breakpoint before exception:

The cause is very obvious, let's add the fix:

for (r += 4; r < o && r < t.byteLength;) {

   // ... SNIP ...

}

After deploying the change above, I no longer see the previous error. But now Unity throws many exceptions which I'm not sure how to handle.

  • [libil2cpp] ERROR: Could not open Il2CppData/Metadata/global-metadata.dat
  • RuntimeInitializeOnLoadManagerInitializer: Failed reading 'RuntimeInitializeOnLoads.json'
  • RuntimeInitializeOnLoadManagerInitializer: Failed reading 'ScriptingAssemblies.json'
  • No GlobalGameManagers file was found at , quitting player!
  • Failed to initialize player

I'll stop here for now. I'll ask around in Unity support forum, hopefully I can get my answer. Cheers!

UPDATE:

After asking around, most people said the issue is due to incorrect content-type / content-encoding. But as seen below, all .br have the correct content-type and content-encoding.

Oops.. .data.br doesn't have the correct content-encoding!!! Let's fix that by adding these lines to NGINX's configuration:

location ~* /unity/.*\.data\.br$ {
	brotli off;
	types {}
	default_type application/octet-stream;
	add_header Content-Encoding br;		 
	add_header X-Powered-By "Test"; 
}

I also need to return build.loader.js into its original state. After making sure all responses are with correct content-encoding, the game loads!

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

Last weekend I decided to revisit Unity Framework. This is my second attempt to understand game programming. Few years back, I did installed the framework, and played around with the sample games. But it was a failure. I was overwhelmed by the editor and concepts. I tried to follow the tutorials, but didn’t stick. So I threw my towel.

To avoid repeating my previous failure, I decided to take a different strategy. Fortunately, my workplace provided us with access to O’Reilly library. With high hope, I picked up this book:

I should be able to finish this book by the weekend, or so I thought. By the second chapter, I was already bored from the lack of action. I feel that I need something more direct, hands-on approach in order to keep me going. I don’t want surrender for the second time. Luckily, I found this course on Linkedin Learning:

The course is slated for 2 hours 22 minutes. But it took me the whole day to complete it. You know what, it was really worth it. It really helped me to open my eyes, demystify the concepts and slowly introduce me to Unity Editor. I was never overwhelmed and thoroughly enjoyed the lessons.

I know the course is quite dated. The course is using Unity 5 (was released in 2015), while what I have in my laptop is Unity 2020. But kudos to Unity, there is not much visible differences between the two versions. Despite a 5-year gap, the controls in Unity Editor haven’t changed drastically.

Once completed the course, they gave me this certificate:

If the terms animation, collision detection, prefabs are foreign to you, and you want to learn Unity Framework, I highly recommend the course above. For now, enjoy the fruit of my weekend of animating sprites using C# scripts:

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant: