In-line conditional and assignment operator


We have operators like +=, *= for addition & assignment, subtraction & assignment respectively. and I’m wondering why we don’t have similar operator for in-line conditional & assignment. Consider two simple operations.

a = b + a;
a = a == 0 ? b : a;

We can reduce the first statement as:

a += b;

As the ternary operator always must return a value, Should I not be able to do the following?

a =? a != 0 : b;
a =?!= 0 : b; // Now, this is kick-ass!
a =:== 0 ? b; // And this is insane.

Noticed the operator =?!= in the second item? This doesn’t exist in C or any other sane programming language, but lets play the game Mr Holmes!
Here a is the isTrue expression as well as the operand. isFalse expression is b. So, the operator implies, assign to the operand the isTrue expression(which is the operand itself as implied by ‘=?’) if the operand is not equal to 0 and otherwise, assign the isFalse expression b. You can infer the third statement the same way.

I’m aware of ?? null coalescing operator which comes close but I’m afraid I can’t check anything other than null.

C#’s extension method may look like an idea but isn’t. I tried to write something like:

/* This code doesn't work */
public static void OnFalse(this ref T item, bool condition, T onFalse)
{
    if (!condition)
    {
        item = onFalse;
    }
}

And to call it like:

a.OnFalse(a == 0, b);

The keyword ref is not supported in extension methods. The idea of returning the value is not productive as it requires you to repeat ‘a’.

There is also a specific solution for the == operator and int type.

public static int SetOnEquals(this int item, int value, int onFalse)
{
    return item == value ? onFalse : item;
}

And call like:

a = a.SetOnEquals(0, b);

This will work, but we did repeat ‘a’ there and our extension method is no longer generic.

Making it a static function,

public static void OnFalse( ref T item, bool condition, T onFalse)
{
    if (!condition)
    {
        item = onFalse;
    }
}

You can call it like:

OnFalse(ref a, a==0, b);

Let’s drop the templates again.

public static void OnEqual( ref int item, int value, int onFalse)
{
    if (item == value)
    {
        item = onFalse;
    }
}

Now the call becomes:

OnEqual(ref a, 0, b);

This is no solution. If you are crazy enough, you can chip in some thoughts!

Workaround for Relative Path / Base URL mismatch on Visual Studio 2012 and Hosting on IIS


This post deals with how we can use relative paths in a .NET web project ( Single Page Application using AngularJS and Bootstrap for cosmetics, ASP.NET MVC4 for hosting WebAPIs and providing initial view.) and make it working properly both when running from Visual Studio as well as after hosting on a Remote Server (IIS). There was a lot of trial and error as well as research carried on to find a sleek solution for this problem. I’m not mentioning each and every bit of it, Let’s jump straight in to the main issues encountered.

There were three areas in which I wanted to use relative paths.

  1. Linking scripts and styles
  2. Ajax calls
  3. Angular routes

For the first one, that is for linking scripts, I got the solution easily which is using  tilde(‘~’) character as prefix as shown below.

<script src="~/Scripts/App.js"></script>

But the second and third apparently didn’t seem to support that solution, So I had to think of some other alternatives. After some research the solution got was to use a base url using the base tag in head node of my Home/Index page.

<base href="/MyApp/"/>

Note: You have to use ‘/MyApp/’. MyApp/ or /MyApp will not work.

In angular js routes I defined it like templateUrl:’Partials/Main.html’ as using slash before will cause it to search in the root folder in IIS. Ajax call urls are given like $http.post(‘api/mymodule/myaction’).

The problem with adding a base URL is that although it works fine in deployment, it breaks in Visual studio as there is no virtual directory with that name. Which means I need a different version of Index.html after publishing. I need the base tag only in published location.  I need to runs some operations post publish to change the source. For this purpose I added the following code in my project file.

  <UsingTask AssemblyFile="bin\PublishTasks.dll" TaskName="PublishTasks.AddBaseURL" />
 <Target Name="CustomTarget" AfterTargets="CopyAllFilesToSingleFolderForPackage"  >
    <AddBaseURL FilePath="$(_PackageTempDir)\Views\Home\Index.cshtml"  BaseURL="/MyApp/">
      <Output TaskParameter="Result" PropertyName="BaseResult" />
    </AddBaseURL>
    <Message Importance="high" Text="Result: $(BaseResult)" />
  </Target>

The first line is for adding the custom task I created to the project.  Find its code below.

namespace PublishTasks
{
    public class AddBaseURL : ITask
    {
        public string BaseURL { get; set; }
        public string FilePath { get; set; }

        [Output]
        public string Result { get; set; }

        #region ITask Members

        public IBuildEngine BuildEngine { get; set; }

        public bool Execute()
        {
            try
            {
                HtmlDocument htmlDoc = new HtmlDocument();
                htmlDoc.Load(FilePath);

                HtmlNode head = htmlDoc.DocumentNode.SelectSingleNode("/html/head");

                HtmlNode baseTag = htmlDoc.CreateElement("base");
                HtmlAttribute href = htmlDoc.CreateAttribute("href");
                href.Value = BaseURL;
                baseTag.Attributes.Add(href);
                head.AppendChild(baseTag);
                htmlDoc.Save(FilePath);
            }
            catch (Exception e)
            {
                Result = "Add BaseURL Error:" + e.ToString();
                return false;
            }

            Result = "Added Base url successfully.";
            return true;
        }

        public ITaskHost HostObject { get; set; }

        #endregion
    }
}

Here I implemented the ITask class to create a custom task. You can find the documentation regarding tasks in Microsoft website. It is having two arguments, FilePath and BaseURL which is given in the project file code above. You can also see that I have used HTMLAgilityPack for easy access of HTML file.

$(PackageTempDir) points to a temporary folder where all projects before publishing is copied to. So, If we edit the file there, it will be reflected in the publish folder as it gets copied. A custom target is used with AfterTargets set to CopyAllFilesToSingleFolderForPackage. The target “AfterPublish” was not working due to a bug in Visual Studio. Now, when we publish after setting the logging level to diagnostic, you can see the following in build log.

2> Using "AddBaseURL" task from assembly "...\PublishTasks.dll".
 2> Task "AddBaseURL"
 2> Task Parameter:FilePath=obj\Release\Package\PackageTmp\Views\Home\Index.cshtml
 2> Task Parameter:BaseURL=/MyApp/
 2> Done executing task "AddBaseURL".
 2> Task "Message"
 2> Task Parameter:Importance=high
 2> Task Parameter:Text=Result: Added Base url successfully.
 2> Message: Result: Added Base url successfully.
 2> Done executing task "Message".

Now, that’s a long fix for a simple issue!