Sunday, 25 September 2016

C#: What is the difference between IQueryable vs IEnumerable?

The main difference between the two is the location of the query execution.

The following example demonstrates the difference:

IQueryable<Model> models = ...
models.Where(x => x.ID ...)

IQueryable is used from LINQ-to-Anything (such as SQL). In this case, the query filter will be executed on the SQL server. This is great for reducing the amount of data returned from the data store.

However, if the code looks as follows:
IEnumerable<Model> models = ...
models.Where(x=> x.ID ...)

The results might be the same but using IEnumerable will cause the query results to be loaded in the memory and the predicate will be executed on the entire result set.

Wednesday, 21 September 2016

C#: How can I get my Selemium test to log into Azure?

I have been writing some entry level Selenium tests for my Azure website that authenticates using Azure AD. The biggest issue is trying to get the WebDriver to authenticate into the solution.

After a lot of learning (read: failed attempts) I have the following solution (read: hack) that seems to work.

1. In my [TestInitialize] method, I load JQuery to the created page

public static class Common
    {
        public static string GetEval(IWebDriver driver, string script)
        {
            IJavaScriptExecutor js = driver as IJavaScriptExecutor;
            return (string)js.ExecuteScript(script);
        }

        public static string GetFile(string path)
        {
            using (var reader = new StreamReader(path))
            {
                return reader.ReadToEnd();
            }
        }
}

Common.GetEval(driver, Common.GetFile("Lib\\jquery.js"));

NOTE: I created a folder called 'lib' and added the jquery.js file. Most importantly, I set the property 'Copy to Output Directory' to 'Copy Always'

2. When I create my connection to the target site, I use JQuery to manipulate the DOM and insert the login credentials. The problem occurs when trying to press 'Enter'. The code simulates pressing 'Enter', waits 5 seconds and then does it again.

 Driver.Navigate().GoToUrl(ConfigurationManager.AppSettings["SiteUrl"]);

            // If we are in the login page, then login
            if (driver.Url.Contains(@"https://login.microsoftonline.com"))
            {
               // set the credentails
                Common.GetEval(driver, "$('#cred_userid_inputtext').val('me@mytenant.onmicrosoft.com')");
                Common.GetEval(driver, "$('#cred_password_inputtext').val('MyPassword123')");

                // press enter
                Common.GetEval(driver, "var e = jQuery.Event('keypress'); e.which = 13; e.keyCode = 13; $('#cred_password_inputtext').trigger(e);");

                System.Threading.Thread.Sleep(5000);

                // press enter again
                Common.GetEval(driver, "var e = jQuery.Event('keypress'); e.which = 13; e.keyCode = 13; $('#cred_password_inputtext').trigger(e);");
            }

3. In the test method, wait 1 second and the DOM should be available.

System.Threading.Thread.Sleep(1000);

var elements = driver.FindElements(By.CssSelector(".myclass"));


Thursday, 8 September 2016

CSS: How do I create a single 'back to top' button?

A little CSS and JQuery can produce a lot of magic in an application. Here is the code.

1. Start with a simple html page. The important item here is to have an 'ID' to navigate to. In my case, I called it 'top'.

<html>
<head>
    <base href="/" />
    <title>Test Page</title>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <script src=”//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js”></script>

    <link href="css/myStuff.css" rel="stylesheet" />
</head>
<body>
    <div>
        <!-- Start Body Content -->
        <div ng-view role="main" id="top"></div>
        <!-- End Body Content -->
    </div>
</body>
</html>

2. Create the element you want to perform the navigation

<a id="backtotop" href="" class="back-to-top hidden" onclick="$('html, body').animate({'scrollTop': $('#top').offset().top}, 500);"><span class="icon-arrow-up"></span>Back to Top</a>

3. Add some CSS

.back-to-top{background-color:blue;bottom:64px;box-sizing:border-box;color:#fff;display:block;height:80px;line-height:1.4em;padding:10px 19px;position:fixed;right:40px;text-align:center;width:77px}
.back-to-top:hover{background-color:green}
.back-to-top [class^="icon-"]{display:block;position:relative;top:-1px}
.back-to-top .icon-arrow-up:before{font-weight:bold;font-size:1.5em}

4. Finally, add come code to make it appear when required. This should go in the 'head' of the html.

    <script>
        var isVisible = false;
        $(window).scroll(function () {
            var shouldBeVisible = $(window).scrollTop() > 300;
            if (shouldBeVisible && !isVisible) {
                isVisible = true;
                $('#backtotop').show();
            } else if (isVisible && !shouldBeVisible) {
                isVisible = false;
                $('#backtotop').hide();
            }
        });
    </script>

You are now good to go.The element can be placed in a any page/module. It will appear when the user has scrolled down the page and will return them to the top.

Thursday, 1 September 2016

SharePoint: Cannot file "Style%2520Library/Js/myfile.js"

I recent SharePoint deployment raised the interesting error about a missing file. When I checked the expected folder, the file was there so the error seemed a little strange.

The solution is in the message:
The missing file is Style%2520Library.

The cause was an incorrect link reference in the masterpage. The link was set to
<SharePoint:ScriptLink Name="~SiteCollection/Style%20Library/JS/myfile.js" runat="server" ID="ScriptLink2" />

SharePoint is url encoding the value. The encoded value of '%' is '%25', which results in the strange url.

I removed the %20 from the link address and the issue was resolved.