Strong typing DisplayAttribute reference to Resources

Let’s say there is a decorated member with DisplayAttribute in code, i.e.:

public enum SomeEnum
{
	[Display(Name = "ResourceKey", ResourceType=typeof(Resource)]
	SomeValue
}

That’s all right except for one problem. If Name is mistyped or given resource key is latter changed then DisplayAttribute will point to an incorrect value and compiler won’t help. Resources designer doesn’t help as well, at least indirectly, because it doesn’t generate externally usable key names. It generates strong typed getters though, like:

internal static string ResourceKey {
        get {
             return ResourceManager.GetString("ResourceKey", resourceCulture);
        }
}

So, these getters are the only strong typed artifact that can be used to achieve strong typed reference. Luckily there is one C# (also VB) feature that was introduced in 6.0 and it is very useful in improving strong typed aspect of code. it is nameof keyword. it is evaluated at compile time and replaces the given expression with a string representation.

In other words, the sample above can be rewritten in strong typed manner:

public enum SomeEnum
{
	[Display(Name = nameof(Resources.ResourceKey), ResourceType=typeof(Resource)]
	SomeValue
}

This way the name is guaranteed to match since it is checked at compile time. So, no more mismatch between the key name and reference to it.

Of course, nameof can be used in many other places. Most notably in INotifyPropertyChanged/MVVM scenario.

Fixing connection problems between Visual Studio and Mac when building iOS applications

I’ve been digging a bit into problems of connection between Visual Studio (Xamarin.iOS) and a Mac and wanted to share a few tips here.

It all started with my Visual Studio being unable to build an iOS application due to the connection issues. Basically I could connect through Xamarin Mac Agent (XMA) through Visual Studio but then the build would fail saying that it couldn’t log to target Mac given my username.

For starters one might read Connecting to the Mac and Connection Troubleshooting topics. But my problem wasn’t listed there or anywhere else. So I had to figure it out on my own.

First hint was that XMA required me to type in the username/password for connecting to the Mac. It connected and I could show the iOS simulator but I couldn’t build. When configured properly it shouldn’t ask for credentials, perhaps only for the first time. For me it was asking for credentials each time I started Visual Studio.

After reading, digging and googling I understood that XMA is using SSH tunnel to connect to the Mac. First thing was inspecting the log files (VS Help/Xamarin/Open Logs…). I didn’t find much there (other than failed connection to the host lines), or so I thought. Next thing was – checking the SSH connectivity (command prompt, ssh username@host). Using my default private key I had no problems connecting to the Mac but Visual Studio kept failing the build process. Next thing to try was Xamarin’s own SSH diagnostics app (provided as C# sources – kudos) which would throw Permission Denied (publickey) upon Connecting to host. Since the public key is on host, the problem obviously has to do with the host – but why since it was working from command prompt. Using this app I also found out what private key is XMA using. And it isn’t my default one, which I tested the connection with.

The thing is that XMA is using its own private key which you can find it at %LocalAppData%Xamarin/MonoTouch/id_rsa. So next thing I tried was connecting through command prompt/ssh using –i PATH argument (forces what key is used), i.e. (replace %LocalAppData% with value) ssh –i %LocalAppData%Xamarin/MonoTouch/id_rsa user@host. And yes, it didn’t work. So definitely a key issue.

The solution

Time for looking at Mac, specially in file /Users/username/.ssh/authorized_keys  where public keys for my profile are stored. And as anybody would guess, it was missing Xamarin’s public key. To get one from the private key I used Puttygen (a part of PuTTY): imported XMA’s private key and copy & pasted the public key portion right into the new line of authorized_keys file on Mac (I had my default public key already in there). This time the ssh command line tool connected without problems. And so did XMA from Visual Studio. Happy me.

The cause

This let me thinking, why does it usually works without intervention. After further examination of log files, it was clear. XMA first tries using its private key, if it doesn’t succeed it tries to cat the public key portion to authorized_keys file on Mac (probably using the credentials you have to enter ). But what happens if the authorized_keys file is read-only? Ha, nothing, a log entry and that’s it. This was my case, I had authorized_keys file as read only. I wouldn’t mind a clear warning: “hey dude, XMA was unable to modify your authorized_keys file, please enter this public_key manually”. It’d certainly spared me some time.

The security considerations

Let me repeat what happens when first time connecting to Mac. XMA would create a private key and put its public part into authorized_keys on Mac. Were you aware of that? No? Neither was I. To make things complicated, the private key in question isn’t password protected. Theoretically an app that user runs (no admin privileges required) could use the key (or worse, copy it through the Internet) to connect to your Mac and gain your credentials on the Mac, which are most probably administration ones. It still would have to type in password for su access, but nevertheless, this isn’t something that should be taken easily IMO.

I certainly wish that the connection mechanism was better documented and people were aware what’s going on. If nothing else, we could pinpoint the problems more easily. Also, an option to use password protected private key would be much more secure.

Use async keyword only when required

While async keyword is very useful it shouldn’t be used when it isn’t required. Imagine this method

public async Task DoSomethingAsync()
{
	await Task.Delay(1000);
}

The method works but it has too much code generated unnecessarily. The thing is that async triggers a lot of code generation at compile time that is invisible at design time. When using .Net Reflector, compiled code looks like:

[AsyncStateMachine(typeof(<dosomethingasync>d__1)), DebuggerStepThrough]
public Task DoSomethingAsync()
{
	<dosomethingasync>d__1 stateMachine = new lt;dosomethingasync gt;d__1 {
		<>4__this = this,
		<>t__builder = AsyncTaskMethodBuilder.Create(),
		<>1__state = -1
	};
	stateMachine.<>t__builder.Start<<dosomethingasync>d__1>(ref stateMachine);
	return stateMachine.<>t__builder.Task;
}

[CompilerGenerated]
private sealed class lt;dosomethingasync>d__1 : IAsyncStateMachine
{
	public int <>1__state;
	public Program <>4__this;
	public AsyncTaskMethodBuilder <>t__builder;
	private TaskAwaiter <>u__1;

	private void MoveNext()
	{
		int num = this.<>1__state;
		try
		{
			TaskAwaiter awaiter;
			if (num != 0)
			{
				awaiter = Task.Delay(0x3e8).GetAwaiter();
				if (!awaiter.IsCompleted)
				{
					this.<>1__state = num = 0;
					this.<>u__1 = awaiter;
					Program.<dosomethingasync>d__1 stateMachine = this;
					this.<>t__builder.AwaitUnsafeOnCompleted gt;taskawaiter program.="" ,=""><dosomethingasync>d__1>(ref awaiter, ref stateMachine);
					return;
				}
			}
			else
			{
				awaiter = this.<>u__1;
				this.<>u__1 = new TaskAwaiter();
				this.<>1__state = num = -1;
			}
			awaiter.GetResult();
			awaiter = new TaskAwaiter();
		}
		catch (Exception exception)
		{
			this.<>1__state = -2;
			this.<>t__builder.SetException(exception);
			return;
		}
		this.<>1__state = -2;
		this.<>t__builder.SetResult();
	}

	[DebuggerHidden]
	private void SetStateMachine(IAsyncStateMachine stateMachine)
	{
	}
}

I won’t dig into what’s actually generated at this point, but while this code is perfectly functional and correct, it is all for nothing in this simple case. Since the only asynchronous operation is the last one, the original method can be easily rewritten as:

public Task DoSomethingAsync()
{
	return Task.Delay(1000);
}

This way it works the same except for the missing pile of generated code.

So, when there is a single asynchronous operation inside the method and no code is executed after it, the async (and await) keyboard can be omitted and you’ll save yourself from too much unnecessarily generated code plu the application will run a bit faster.