Integrating ASPNET MVC views into SharePoint

Introduction

In this post I will cover an approach you can use to surface MVC views into SharePoint pages. I’m also making an assumption that you are familiar with ASPNET MVC, if you are new to ASPNET MVC have a look at this link http://www.asp.net/mvc

Approach

mvcspintegration

Assuming you have developed and published your MVC application to one or more IIS web severs, to surface the MVC views inside a SharePoint page, we can simply create a new content page and add a ‘div” container element, along with some javascript to make Ajax request to MVC controller. After successful completion of request, response is then injected into container “div” element using jQuery.

Snippet below shows HTML markup and JavaScript that can be added to SharePoint page where MVC views needs to be surfaced:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

<script type="text/javascript">

_spBodyOnLoadFunctions.push(function(){

$.ajax({

                type: "GET",

                url: "http://controls.ram.dev/home/documents",

        beforeSend: function(){

            $("#mvchost").html('<img src="/_layouts/images/ajax-loading.gif" />');            

        },

                success: function (result) {

                    $("#mvchost").html(result);

                },

                error: function (xhr, status, error) {

                    alert(error);

                }

            });

});

</script>

<div id="mvchost"></div>

Cross domain scenarios

Because of the same origin policy, cross domain ajax requests are not allowed, so if your SharePoint site and MVC application have different URLs, ajax requests originating from SharePoint site will fail. We can have script tags that loads javascript files from other domains. JSONP uses this approach in order to make cross domain requests by dynamically creating a script tag with necessary URL, On the server you have to wrap the data (typically in JSON format) in a function call (callback). When the script is loaded browser will call the callback function and passes the loaded data. Keeping this in mind we’ll need to make some changes to your MVC application to support cross domain ajax requests.

Adding JSONP support to JsonResult

Methods in controller return “ActionResult”, If you are new to MVC and is not quite familiar with what “ActionResult” is see this blog post http://rachelappel.com/asp.net-mvc-actionresults-explained. There is “JsonResult” class available by default within System.Web.Mvc which is used to send JSON formatted content to the response, we’ll need to extend this to support JSONP

Add a new class to your MVC project and name it “JsonpResult”, derive this class from “JsonResult”. Override the ExecuteResult method to generate callback function call with data wrapped. See code below for “JsonpResult” class

public class JsonpResult : JsonResult

{

    public string Callback { get; set; }

 

    public override void ExecuteResult(ControllerContext context)

    {

        if (context == null)

        {

            throw new ArgumentNullException("context");

        }

 

        this.Callback = context.HttpContext.Request["callback"];

 

        if (string.IsNullOrEmpty(this.Callback))

            throw new ArgumentNullException("Callback required for JSONP response.");

 

        HttpResponseBase response = context.HttpContext.Response;

 

        if (!String.IsNullOrEmpty(ContentType))

        {

            response.ContentType = ContentType;

        }

        else

        {

            response.ContentType = "application/json";

        }

        if (ContentEncoding != null)

        {

            response.ContentEncoding = ContentEncoding;

        }

        if (Data != null)

        {

            JavaScriptSerializer serializer = new JavaScriptSerializer();

            response.Write(string.Format("{0}({1});", this.Callback, serializer.Serialize(Data)));

        }

    }

}

Next thing we’ll need to do is to create an extension method on Controller class to Render view as string, this is so we can send the output as a JSON response.

public static string RenderPartialView(this Controller controller, string viewName, object model)

{

    if (string.IsNullOrEmpty(viewName))

        viewName = controller.ControllerContext.RouteData.GetRequiredString("action");

 

    controller.ViewData.Model = model;

    using (var sw = new StringWriter())

    {

        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);

        var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);

        viewResult.View.Render(viewContext, sw);

 

        return sw.GetStringBuilder().ToString();

    }

}

Lastly we’ll need to add an additional action method on Controller that returns JsonpResult (This is the extended JsonResult class we created that can handle cross domain requests using JSONP). In this method you will need to add logic to get data needed for the view and return a new instance of “JsonpResult” as shown in sample below.

var model = null;

 

//Add data Access logic here

 

return new JsonpResult

{

    Data = new {

        success = true,

        message = "View Loaded Successfully",

        view = this.RenderPartialView("{replace with view}", model)

    },

    JsonRequestBehavior = JsonRequestBehavior.AllowGet

};

We will also need to modify the javascript snippet that is added to SharePoint page which will send ajax request to controller to use JSONP because of cross domain scenario. Here is the modified snippet that uses JSONP

<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

<script type="text/javascript">

_spBodyOnLoadFunctions.push(function(){

$.ajax({

                type: "GET",

                url: "http://controls.ram.dev/home/documentsjsonp",

        dataType: "jsonp",

        crossDomain: true,

        beforeSend: function(){

            $("#mvchost").html('<img src="/_layouts/images/ajax-loading.gif" />');            

        },

                success: function (result) {

                    $("#mvchost").html(result.view);

                },

                error: function (xhr, status, error) {

                    alert(error);

                }

            });

});

</script>

<div id="mvchost"></div>

if you notice in above javascript, in the success callback function, I’m grabbing the view markup from result which is now returned as a JSON response from controller action method and injecting into container div using jQuery. Ajax request URL is also different since we have additional action method in controller that returns JSON result for cross domain requests.

Some thoughts on authentication scenarios

If your SharePoint site is configured for SAML Claims authentication, you’ll need to make your MVC application also trust the same identity provider, this will provide SSO across SharePoint and MVC application. Security logic can be added in your controller methods for ex. if you need to retrieve data specific to authenticated user.

I haven’t tested with FBA sites, may be I will create a part 2 of this post to cover some authentication related scenarios.

Additional use cases for this approach

There are some additional scenarios and use cases where the same approach can be beneficial.

  • You are developing custom applications on SharePoint and you either are not on SharePoint 2013 to take advantage of Provider hosted app model or you have some constraints on using App model (In this case controller methods could talk back to SharePoint using SharePoint APIs)
  • You have a need to surface content from other systems into SharePoint

Hope this helps…

Cheers,

</Ram>

Office 2013 – How to get rid of extra space between commands

If you got a non-touch laptop and you use office 2013 and notice extra space between commands on ribbon in office 2013, reason for this is that your office 2013 is in touch optimized mode, follow steps below to switch to optimized for mouse mode which will get rid of the extra spaces between commands.

From the quick access toolbar select “touch/mouse mode” this will bring up an addition item onto the toolbar, see screenshot below

image

Clicking this option will bring up a drop menu which allows you to switch between mouse and touch, switch to mouse and you will find extra spaces between commands on ribbon disappearing. This change is global and affects across the entire office suite, meaning if you change in word, you’ll see it on outlook, excel etc.

Hope this helps someone, thanks to my colleague for this tip

Cheers,

</Ram>

An Introductory post (thisdevmind.com)

This is an introductory post to announce my new site, while I’m certainly not new to blogging, one of the things I realized is that since I started blogging initially on MSDN,  I’ve moved my blog from MSDN to other hosting providers and then coming back to MSDN while not maintaining consistent URL and preserving links to many of my older posts, I realize how frustrating this has been to readers of my blog. Granted not sure if many people read stuff I write :) but still…

I wanted to write this post and set the record straight “I screwed up”, I can assure you this site is here to stay, I’m currently hosting this blog on Azure websites using WordPress. I hope I wont have to move to another provider, even if I do I will take every step to ensure consistency on URL and preserve links to posts so you’ll never see broken links to my posts. Through this site I’m hoping to share information about developing for cloud and devices and hope you will find the site useful. I hope you will stay in touch with me through various options listed in contact page of this site and provide me any feedback you might have on the content here or things I can improve.

Cheers,

</Ram>

Targeting windows 8 platform when developing windows store apps using VS2013 + Win 8.1

Like most of the developers who always like to run on latest and greatest Microsoft software, I too upgraded my machine to Windows 8.1 and VS 2013, Today I was bit disappointed to find out that I could not develop windows store app and target windows 8 platform. When creating new projects in VS2013 using the windows store project templates, 8.1 is picked as a default for me, there is simply no way to change this to 8.0 through the VS UI, I tried editing the csproj file and changing the target platform version from 8.1 to 8.0, while that seem to change the target platform after I reloaded the project it broke a bunch of stuff.

For now it seems like you have to keep both VS 2012 and VS 2013 side by side if you will be doing any windows store app development and want to target 8.0. VS 2013 project templates for windows store apps are designed to work with Windows 8.1 only. I don’t like that I have to have two versions of VS in my dev machine but it is what it is. If you have any work around or suggestions, please post a comment

Thanks,

</Ram>

Sending email from windows store apps using SendGrid Web Api and HTTP Client

One of the things you will notice when working on windows store applications is that there isn’t any api’s within windows runtime or .NET for Windows Store apps for sending emails. You can of course have a hyperlink button with navigateUri set to mailto:somebody@somecompany.com for ex. to send emails using the mail client installed. What if you want to attach a file or generate email in a specific format or have a cool UI in your app for allowing users to contact you as app developer? In this post I will walk through how I used SendGrid and HTTP client to accomplish just that. One thing I want to point out that the C# SDK from SendGrid cannot be used in windows store apps due to references to API’s and libraries that aren’t simply supported in windows store apps. This is the primary reason why I chose to use HTTP client and roll my own service that Views and ViewModels within my app can consume.

If you are not familiar with SendGrid Web Api check out this awesome documentation from SendGrid team http://sendgrid.com/docs/API_Reference/Web_API/index.html

If you have never used SendGrid before you can check out more info at their site http://sendgrid.com, Its super easy to sign up. Best part is SendGrid is also available for use within your cloud applications in Windows Azure. Really a great example of an excellent online service, cloud enabled and you can use it from anywhere, web, devices, etc.

Define a new class called EmailMessage in your windows store project as shown below, basically this class will be used as a data object when sending emails from your app using email service that we will define later.

internal class EmailMessage

{

    public string From { get; set; }

    public string FromEmail { get; set; }

    public string To { get; set; }

    public string ToEmail { get; set; }

    public string Subject { get; set; }

    public string Body { get; set; }

    public IReadOnlyList<StorageFile> Attachments { get; set; }

}

Next we define an interface called IEmailService, see below

interface IEmailService

{

    string ApiUser { get; }

    string ApiKey { get; }

 

    Task<String> SendEmail(EmailMessage message);

}

Now we’ll define the EmailService class which will implement the IEmailService interface. In this class I defined constants to hold the SendGrid web api parameter names.
 
In the constructor I set the ApiUser and ApiKey property by reading values stored in Resource file. You probably should store these in a more secure location as one could easily reflect the assembly and see the values from Resource files.

SendEmail Implementation

The implementation for SendEmail method is quite straight forward, see the code below. Below Implementation also supports sending attachments, EmailMessage class has a property which is a read only collection of StorageFiles, this can be set from calling method if out going email message requires file attachments.

public async Task<string> SendEmail(EmailMessage message)

{

   HttpClient httpClient = null;

   string responseData = string.Empty;

   try

   {

       using (var postData = new MultipartFormDataContent())

       {

           var subjectContent = new StringContent(message.Subject);

           subjectContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = SubjectParam

           };

           postData.Add(subjectContent);

           var bodyContent = new StringContent(message.Body);

           bodyContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = HtmlParam

           };

           postData.Add(bodyContent);

           //setup api key and api user param

           var apiUserContent = new StringContent(ApiUser);

           apiUserContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = ApiUserParam

           };

           postData.Add(apiUserContent);

           var apiKeyContent = new StringContent(ApiKey);

           apiKeyContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = ApiKeyParam

           };

           postData.Add(apiKeyContent);

           var fromNameContent = new StringContent(message.From);

           fromNameContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = FromNameParam

           };

           postData.Add(fromNameContent);

           var fromContent = new StringContent(message.FromEmail);

           fromContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = From

           };

           postData.Add(fromContent);

           StringContent toContent = new StringContent(message.ToEmail);

           toContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = ToParam

           };

           postData.Add(toContent);

           var toNameContent = new StringContent(message.To);

           toNameContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

           {

               Name = ToNameParam

           };

           postData.Add(toNameContent);

           if (message.Attachments.Count() > 0)

           {

               foreach (var attachment in message.Attachments)

               {

                   Stream fs = await attachment.OpenStreamForReadAsync();

                   postData.Add(AddFile(fs, FilesParam, attachment.Name));

               }

           }

           string fullUrl = string.Format("https://{0}{1}", SendGridHost, Uri);

           httpClient = new HttpClient();

           HttpResponseMessage response = await httpClient.PostAsync(new Uri(fullUrl), postData);

           using (HttpContent content = response.Content)

           {

               responseData = await content.ReadAsStringAsync();

           }

           if (response.StatusCode != System.Net.HttpStatusCode.OK)

               throw new Exception(responseData);

       }

       return responseData;

   }

   finally

   {

       if (httpClient != null)

           ((IDisposable)httpClient).Dispose();

   }

}

Handling File Attachments

Helper method for file attachments for emails.

private StreamContent AddFile(Stream stream, string name, string fileName)

{

    var fileContent = new StreamContent(stream);

    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")

    {

        Name = string.Format("{0}[{1}]", name, fileName),

        FileName = fileName

    };

    fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    return fileContent;

}

 

Sending Email

Here is an example of sending email using the service from your windows store app, I’m using ServiceLocator to get an instance of email service.

IEmailService emailService = ServiceLocator.Current.GetInstance<IEmailService>();

await emailService.SendEmail(new EmailMessage()

{

    To = "Someone",

    ToEmail = "someone@somecompany.com",

    From = "",

    FromEmail = "",

    Body = "Sending Email from Windows Store apps",

    Subject = "Sending Email from Windows Store apps",

    Attachments = new ReadOnlyCollection<StorageFile>(attachments)

});

I will be publishing a Sample to MSDN code sample site and will update this post with links

Hope this helps

Cheers,

</Ram>

Annoying experience with TFS Online

Hope this post doesn’t come across as a rant but just wanted to share the experience I had with tfsonline service, hopefully someone in charge of this service will see this and take some action.

If you are not familiar with tfsonline, simplistic way to think about it is that its a hosted TFS offering completely managed by Microsoft. As an MSDN subscriber you get this pretty much free of cost. I use it for all my personal projects.

Now to main reason for this post, I was trying to help out a friend (Fabian) with an issue and he granted me access to his project in TFS Online. After he granted me access I received following email from the service

image

 

I clicked on “Accept the Invitation” link and it took me to http://tfs.visualstudio.com, I sign to the service using my live id credentials and I get following screen

image

At this point I’m wondering where on earth is Fabian’s project that he just granted me access to? It would have been very helpful if the above UI showed that, Unfortunately as you can see from screen shot it doesn’t.

If I know Fabian’s TFS service address I could simply connect to his project via Web or from VS using the URL and signing in with my live ID.

Hope Microsoft will fix this soon and include the projects I have access to in the screen above which will allow me to connect to another users project because currently it’s quite confusing and requires a manual step

Cheers,

</Ram>

List of windows store app bar button styles

By default when you create Windows Store Application using the Visual Studio project templates, Visual Studio adds a XAML resource dictionary (“StandardStyles.xaml”) file under common folder, this file contains styles that really simplify application development and ships with a set of App Bar button styles. These styles are by default commented, you can simply uncomment the ones you are using in your project.

I’ve listed each style here in the post with a visual image so you understand what’s available to use within your application and know how it looks like visually, If for some reason you don’t like the default text used in these buttons you can simply edit the property setter value named “AutomationProperties.Name”, defined in the StandardStyles.xaml file. Hopefully this will save you some time

To use these buttons simply add a button control and set the style property, see example below

<Button
      Style="{StaticResource RefreshAppBarButtonStyle}" />

STYLE

VISUAL

RefreshAppBarButtonStyle image
SkipBackAppBarButtonStyle image
SkipAheadAppBarButtonStyle image
PlayAppBarButtonStyle image
PauseAppBarButtonStyle image
EditAppBarButtonStyle image
SaveAppBarButtonStyle image
DeleteAppBarButtonStyle image
DiscardAppBarButtonStyle image
RemoveAppBarButtonStyle image
AddAppBarButtonStyle image
NoAppBarButtonStyle image
YesAppBarButtonStyle image
MoreAppBarButtonStyle image
RedoAppBarButtonStyle image
UndoAppBarButtonStyle image
HomeAppBarButtonStyle image
OutAppBarButtonStyle image
NextAppBarButtonStyle image
PreviousAppBarButtonStyle image
FavoriteAppBarButtonStyle image
PhotoAppBarButtonStyle image
SettingsAppBarButtonStyle image
VideoAppBarButtonStyle image
DownloadAppBarButtonStyle image
MailAppBarButtonStyle image
SearchAppBarButtonStyle image
HelpAppBarButtonStyle image
UploadAppBarButtonStyle image
EmojiAppBarButtonStyle image
TwoPageAppBarButtonStyle image
LeaveChatAppBarButtonStyle image
MailForwardAppBarButtonStyle image
ClockAppBarButtonStyle image
SendAppBarButtonStyle image
CropAppBarButtonStyle image
RotateCameraAppBarButtonStyle image
PeopleAppBarButtonStyle image
ClosePaneAppBarButtonStyle image
OpenPaneAppBarButtonStyle image
WorldAppBarButtonStyle image
FlagAppBarButtonStyle image
PreviewLinkAppBarButtonStyle image
GlobeAppBarButtonStyle image
TrimAppBarButtonStyle image
AttachCameraAppBarButtonStyle image
ZoomInAppBarButtonStyle image
BookmarksAppBarButtonStyle image

DocumentAppBarButtonStyle

image
ProtectedDocumentAppBarButtonStyle image
PageAppBarButtonStyle image
BulletsAppBarButtonStyle image
CommentAppBarButtonStyle image
Mail2AppBarButtonStyle image
ContactInfoAppBarButtonStyle image
HangUpAppBarButtonStyle image
ViewAllAppBarButtonStyle image
MapPinAppBarButtonStyle image
PhoneAppBarButtonStyle image
VideoChatAppBarButtonStyle image
SwitchAppBarButtonStyle image
ContactAppBarButtonStyle image
RenameAppBarButtonStyle image
PinAppBarButtonStyle image
MusicInfoAppBarButtonStyle image
GoAppBarButtonStyle image
KeyboardAppBarButtonStyle image
DockLeftAppBarButtonStyle image
DockRightAppBarButtonStyle image
DockBottomAppBarButtonStyle image
RemoteAppBarButtonStyle image
SyncAppBarButtonStyle image
RotateAppBarButtonStyle image
ShuffleAppBarButtonStyle image
ListAppBarButtonStyle image
ShopAppBarButtonStyle image
SelectAllAppBarButtonStyle image
OrientationAppBarButtonStyle image
ImportAppBarButtonStyle image
ImportAllAppBarButtonStyle image
BrowsePhotosAppBarButtonStyle image
WebcamAppBarButtonStyle image
PicturesAppBarButtonStyle image
SaveLocalAppBarButtonStyle image
CaptionAppBarButtonStyle image
StopAppBarButtonStyle image
ShowResultsAppBarButtonStyle image
VolumeAppBarButtonStyle image
RepairAppBarButtonStyle image
MessageAppBarButtonStyle image
Page2AppBarButtonStyle image
CalendarDayAppBarButtonStyle image
CalendarWeekAppBarButtonStyle image
CalendarAppBarButtonStyle image
CharactersAppBarButtonStyle image
MailReplyAllAppBarButtonStyle image
ReadAppBarButtonStyle image
LinkAppBarButtonStyle image
AccountsAppBarButtonStyle image
ShowBccAppBarButtonStyle image
HideBccAppBarButtonStyle image
CutAppBarButtonStyle image
AttachAppBarButtonStyle image
PasteAppBarButtonStyle image
FilterAppBarButtonStyle image
CopyAppBarButtonStyle image
Emoji2AppBarButtonStyle image
ImportantAppBarButtonStyle image
MailReplyAppBarButtonStyle image
SlideShowAppBarButtonStyle image
SortAppBarButtonStyle image
ManageAppBarButtonStyle image
AllAppsAppBarButtonStyle image
DisconnectDriveAppBarButtonStyle image
MapDriveAppBarButtonStyle image
NewWindowAppBarButtonStyle image
OpenWithAppBarButtonStyle image
ContactPresenceAppBarButtonStyle image
PriorityAppBarButtonStyle image
UploadSkyDriveAppBarButtonStyle image
GoToTodayAppBarButtonStyle image
FontAppBarButtonStyle image
FontColorAppBarButtonStyle image
Contact2AppBarButtonStyle image
FolderppBarButtonStyle image
AudioAppBarButtonStyle image
PlaceholderAppBarButtonStyle image

ViewAppBarButtonStyle

image
SetLockScreenAppBarButtonStyle image
SetTitleAppBarButtonStyle image
CcAppBarButtonStyle image
StopSlideShowAppBarButtonStyle image
PermissionsAppBarButtonStyle image
HighlightAppBarButtonStyle image
DisableUpdatesAppBarButtonStyle image
UnfavoriteAppBarButtonStyle image
UnPinAppBarButtonStyle image
OpenLocalAppBarButtonStyle image
MuteAppBarButtonStyle image
ItalicAppBarButtonStyle image
UnderlineAppBarButtonStyle image
BoldAppBarButtonStyle image
MoveToFolderAppBarButtonStyle image
LikeDislikeAppBarButtonStyle image
DislikeAppBarButtonStyle image
LikeAppBarButtonStyle image
AlignRightAppBarButtonStyle image
AlignCenterAppBarButtonStyle image
AlignLeftAppBarButtonStyle image
ZoomAppBarButtonStyle image
ZoomOutAppBarButtonStyle image
OpenFileAppBarButtonStyle image
OtherUserAppBarButtonStyle image
AdminAppBarButtonStyle image
StreetAppBarButtonStyle image
MapAppBarButtonStyle image
ClearSelectionAppBarButtonStyle image
FontDecreaseAppBarButtonStyle image
FontIncreaseAppBarButtonStyle image
FontSizeAppBarButtonStyle image
CellphoneAppBarButtonStyle image
ReshareAppBarButtonStyle image
TagAppBarButtonStyle image
RepeatOneAppBarButtonStyle image
RepeatAllAppBarButtonStyle image
OutlineStarAppBarButtonStyle image
SolidStarAppBarButtonStyle image
CalculatorAppBarButtonStyle image
DirectionsAppBarButtonStyle image
TargetAppBarButtonStyle image
LibraryAppBarButtonStyle image
PhonebookAppBarButtonStyle image
MemoAppBarButtonStyle image
MicrophoneAppBarButtonStyle image
PostUpdateAppBarButtonStyle image
BackToWindowAppBarButtonStyle image
FullScreenAppBarButtonStyle image
NewFolderAppBarButtonStyle image
CalendarReplyAppBarButtonStyle image
UnsyncFolderAppBarButtonStyle image
ReportHackedAppBarButtonStyle image
SyncFolderAppBarButtonStyle image
BlockContactAppBarButtonStyle image
SwitchAppsAppBarButtonStyle image
AddFriendAppBarButtonStyle image
TouchPointerAppBarButtonStyle image
GoToStartAppBarButtonStyle image
ZeroBarsAppBarButtonStyle image
OneBarAppBarButtonStyle image
TwoBarsAppBarButtonStyle image
ThreeBarsAppBarButtonStyle image
FourBarsAppBarButtonStyle image

 

 

HOW-TO: Generate hash in windows store apps

This post shows how to generate hash using SHA1 algorithm in windows store apps, useful if your app makes calls to rest api’s that require app to pass an api signature as header or querystring

 

Import following namespaces 

using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
 
Convert the string to binary
 
IBuffer buffer = CryptographicBuffer.ConvertStringToBinary(text, BinaryStringEncoding.Utf8);

Create the hash
 
HashAlgorithmProvider provider = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1);

//hash it

IBuffer hash = provider.HashData(buffer);

Create a base64 encoded string

CryptographicBuffer.EncodeToBase64String(hash);

Base64 encoded string can be used as API signature

 

You can wrap this functionality into a nice helper class and reuse, see full code below 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Windows.Security.Cryptography;

using Windows.Security.Cryptography.Core;

using Windows.Storage.Streams;

 

    


    internal static class Helper

    {

        public static string ComputeHash(string text)

        {

            string base64Encoded = string.Empty;

            IBuffer buffer = CryptographicBuffer.ConvertStringToBinary(text, BinaryStringEncoding.Utf8);

            HashAlgorithmProvider provider = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1);

            //hash it

            IBuffer hash = provider.HashData(buffer);

            base64Encoded = CryptographicBuffer.EncodeToBase64String(hash);

            return base64Encoded;

        }

        

    }

    

Cheers,

</Ram>

When typing PowerShell ISE in start screen opens in PowerShell command line and not PowerShell ISE

I recently encountered a windows 8 bug that took me a bit to figure out the exact root cause, posting it here incase anyone run into this in future.

Subject of the post basically sums up the issue. Root cause was in my roaming profile I had a Shortcut named “PowerShell ISE” which was referring the command line powershell instead of powershell_ise.exe.

How the shortcut got created in my roaming settings completely beats me, if you encounter the same issue you can simply check “C:\Users\[windows logon]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs” for a shortcut named “PowerShell ISE” and either delete the shortcut or update in properties to point to powershell_ise.exe instead of powershell.exe

Hope that saves someone else time in future

Cheers,

</Ram>

Recovering data from an unattached content database using PowerShell

One of the really nice IT Pro features in SharePoint, introduced back in SharePoint Server 2010 is a feature called “recover data from an unattached content database”. It allows us to perform a granular recovery of content from an unattached content database (content database restored from a backup). I’m sure many of you are already familiar with this feature and have probably seen various demos etc. so I’m not going to re-hash it here.

Feature is pretty well documented here http://technet.microsoft.com/en-us/library/hh269602.aspx, unfortunately the problem is if you pay close attention to this TechNet article especially where they talk about how to recover data from an unattached content database using PowerShell you will find that it is not complete, in fact not even close.

While it is a pretty nice feature there are too many moving parts, what I mean is you have to restore the database first, then you have to export the list out of unattached content database using Central Administration UI, then you have to run Import-SPWeb PowerShell to actually import the list into the site where you want to recover the deleted list.

I created a PowerShell to automate the exporting of list from an unattached content database and importing to the site, you still need to restore content database from a backup prior to running the script. You can get the script from here http://gallery.technet.microsoft.com/Recover-List-from-an-04fa609a

Cheers,

</Ram>