Dot Net Mafia

Group site for developer blogs dealing with (usually) .NET, SharePoint 2013, SharePoint 2010, Office 365, SharePoint Online, and other Microsoft products, as well as some discussion of general programming related concepts.

This Blog



Corey Roth [MVP]

A SharePoint MVP bringing you the latest time saving tips for SharePoint 2013, Office 365 / SharePoint Online and Visual Studio 2013.
  • Office 365 Groups or Team Sites? No need to have that discussion any more!

    Any time Microsoft releases a new feature that has an overlap with a new feature, we see a flurry of fluff in the form of blog posts and even sessions on which feature to use when?  When Office 365 Groups came out, this was no exception.  What has changed?  At the Future of SharePoint event, Microsoft announced that every group in Office 365 will benefit from an associated Team Site.  Every Office 365 Group you create will get a new modern Team Site provisioned that shows a clear linkage to the Group.


    That’s pretty cool and should help eliminate the confusion on what to use when since you no longer have to make a decision.  Microsoft has also stated that existing Office 365 Groups (as in the ones you have now) will also get a Team Site associated with them as well.  This means whatever you are doing now, it’s ok.  You’ll be in good shape when the new features are rolled out.

    The updated Team Site home page provides a quick way to find the most important and relevant content on the site.  Content and news can be pinned to the front page and the Office Graph is baked right in to highlight activity relevant to you.  What’s even better is that you can even access it through the new SharePoint mobile app.

    Another exciting change from the new Team Site experience is that they will be provisioned faster.  Whereas, it used to take several minutes to provision a site collection, now it should only be a matter of seconds. 

    Between the Office 365 Group, the new team site home page, and existing team sites, we haven’t seen quite how all of this ties together yet.  It will be interested to see where things go.

    This isn’t out yet, where should I put content right now?

    Ok, so the conversation is not quite dead yet.  For now, if you need features that are only in Team Sites such as workflow or metadata, use a Team Site.  If you don’t care about Metadata and the document library in Office 365 Groups is good enough for you, then use that.  As you can see, Office 365 Groups is really starting to tie everything together.

  • One key takeaway from SharePoint 2016 General Availability

    This morning at the Future of SharePoint event, Microsoft announced the General Availability (GA) of SharePoint Server 2016.  While many customers have transitioned to the cloud with Office 365, on-premises SharePoint is still very real and alive.  As an end user, you might have looked at SharePoint Server 2016 and wondered “Why bother?”.   There really isn’t many new features that the end user is going to get excited about.  Yes, you’ll get a nice new suite bar, but most of the rest of the features the user cares about are linked to hybrid scenarios.

    What you should take away from today’s event is that you are not upgrading to SharePoint Server 2016 for what you get today.  You are upgrading for what you get in the future.  Whereas previous versions of SharePoint Server were very much static and didn’t change over the three year release cycle, this version is very different.  This version lays the foundation for new features to be delivered through Feature Packs.  These Feature Packs will bring new features to your on-premises SharePoint farm without having to wait until the next big version.  Microsoft even plans on delivering a set of capabilities specific to the needs of on-premises customers.

    Don’t worry, new features won’t just show up overnight like in Office 365.  Instead, as a SharePoint administrator, you’ll be able to have control over which features you enable in your farm.  This will give you time to plan and communicate change accordingly.  For whatever reason you run on-premises SharePoint, this should be an exciting announcement as it means you won’t get left in the cold waiting for the latest killer feature.  Does that mean, every feature from Office 365 is coming down to on-premises? No.  Some features simply aren’t feasible on-premises.  That’s why the hybrid story is so important.  However, it does mean, you’ll get updates on-premises faster than ever before.

    Feature Packs will be delivered through the public update channel starting in 2017.  Microsoft will announce more details about the upcoming Feature Packs in the coming months.  To get the new Feature Pack, your company will have to have purchased SharePoint with Software Assurance.  For Enterprise customers, that’s probably most of you.  You’ll notice this is similar to the model that Windows 10 is using and the way it updates as well.

    There is an exciting road ahead for SharePoint.  Be sure and read everything about it in case you missed any of it.

  • About to start a major Intranet project? Take a step back and see what’s coming to SharePoint

    For years, enterprise have been spending huge amounts of money and time building their Intranet on top of the SharePoint platform.  Intranets take lots of planning and development even to get the most basic of functionality.  Throw in heavy branding and responsive design and you’re looking at a significant investment.  Launching a new Intranet has just been too long of a process with too many technical hurdles, but things are going to improve.

    SharePoint team site and mobile app

    Microsoft has announced a new page publishing experience that will make a lot of publishing scenarios much simpler.  It provides an updated page authoring canvas that allows for simple branding and page layouts while still having some extensibility hooks.  Best of all what you create here is responsive and works seamlessly with the new SharePoint app.  Out-of-the-box you will be able to quickly creates pages without a bunch of up-front configuration first.  Remember what you had to do before?  You know, create content types, page layouts, master pages, workflows, page libraries and more.  Not to mention, Microsoft has been telling you to stop customize master pages for some time now.  You want to go back to that?

    SharePoint becomes a first class citizen in Office 365 – a few years ago, you might nave noticed that references to the actual term SharePoint were few and far between in Office 365.  The only real entry point to SharePoint was through the Sites link in the app launcher.  That’s changing.  The link will now say SharePoint in it and so will the navigation in the suite bar.  Clicking on the link will take you to the new entry point or SharePoint Home which pushes sites that you frequent right to the center.  It also tracks sites you are following as well as provides links to other sites.  This should make it easier to find many of the sites you need without an organization having to put a lot of thought into the information architecture.  While it won’t outright replace it.  It’s a great starting point for organizations who have never bothered to really set anything up like that.

    SharePoint home page with activity - 100 percent

    But my Intranet *MUST* do X or we can’t use it – great!  Keep doing what you are doing and customize the whole thing the way you used to.  However, if your requirements are flexible, the first release may be just what you need.  If you are looking for a simple page authoring canvas with little ramp-up, I think you are going to like it.  This upcoming release, I think will come close to hitting the “80%” mark where it’s good enough to get people publishing content quickly and easily.  If you have advanced needs and you find that you need something more, then you are probably going to have to go back to the conventional publishing model while you wait for new features to come online in future releases.

    The Intranet, not just for huge Enterprises any more.  I have worked at a number of consulting companies and there is good money in helping clients build out elaborate Intranets.  Sure a lot of that comes down to the planning and design, but the implementation was just overly complex.  Just as Office 365 has brought features like Team Sites and Exchange into small organizations years ago, the new modern pages experience is making the Intranet broadly available to smaller organizations.  That’s pretty exciting.


    We are about to start a big Intranet project or are in the middle of one – This is a tricky place to be in and your organization will have to make decisions about timelines.  The new SharePoint Home entry will be here soon but the modern page publishing features are further out in 2016.  Although there is limited information right now.  Try and take a look at your requirements and see if the new Modern pages experience will meet your requirements.  If you don’t think it will, them continue implementing your new Intranet as usual and take another look at it in the future.  If you think it does meet your requirements, then maybe take a step back and see what happens and use this as an opportunity to fully vet out your define phase.  Ultimately, it comes down to your organization’s priorities, requirements, and timelines.

    The future of SharePoint is bright.  Today has taught us that Microsoft is continuing to invest in the product as a core.  If you missed any of the announcements, be sure and read through them to find out everything that’s coming.

  • Getting started with Azure App Service and Easy Tables

    Azure App Service makes it easy to build a back-end for a mobile application.  One of my favorite features of it is Easy Tables.  Easy Tables makes it easy to create tables in a SQL Azure database and comes with an SDK for several mobile platforms that make it easy to access it.  You can make calls to it using REST, but there are APIs for Apache Cordova, Xamarin, as well as native development.  Some of the APIs even support offline synchronization.  If you are looking to prove out an idea, Easy Tables makes it well, easy.

    There is some great documentation out there for getting started with Easy Tables as well.  However, I ran into a few stumbling points in my early experiences that I thought I would share.  These instructions assume, you have created an Azure App Service app.  If you don’t have one just look for App Services in your Azure portal and click New.  In our case, we are going to be working with a node.js back-end.

    Setting up the database connection

    Setting up the database connection should be simple, but unfortunately, it’s not due to issues in the configuration UI.  Before you go to set up the connection, you will need to create a SQL Server to host your database if you don’t have one already.  This isn’t terribly complicated just try to pick a region close to the one hosting your App Service App.  After your database is set up, you need to create the database to host your data.  You can use the free pricing tier too to try things out if you haven’t created a free database in this particular region yet (you only get one per region).


    Once you have your database set up, you are ready to configure a connection to from Azure App Service.  Effectively, you are creating a connection string.  To set up the connection, go to your App Service App and click on the Easy Tables link under Mobile.


    It will then initialize Easy Tables if needed and prompt you to click continue to set it up.


    Here is where, it will prompt you to connect to a database.


    After this, it will prompt you to select your existing SQL Server and then database.  The final step is to enter in the username and password you set on your SQL Server and database.  Specify a connection string name (whatever you want) along with the credentials.  Click ok and hope for the best.  I mentioned I had problems with the UI right?  The first time I did this, I couldn’t get it to save my password because it had a semicolon (;) in it.  Remember, how I said it is building a connection string underneath?  Semicolon is a delimiter for connection strings and the UI doesn’t handle that at all.  It just fails.  Hopefully this step works for you.  If it doesn’t there is a way that you can manually set the connection string using Resource Explorer.  That’s more detail than I want to go into today.  If you run into it though, feel free to ping me or leave me a comment and I’ll provide the details.

    Once your database connection has been set up, click on the Initialize App button.  This will destroy any files that may already exist on your App Service App so don’t click it if there is something you need there.  Effectively this sets up folders such as /tables and /api as well as some of the basic node.js configuration.  It also creates a test table called TodoItem.

    Creating new tables

    There are a few ways to create new tables but not all of them have the desired results:

    • Create the appropriate files in the tables folder
    • Create the table through the Azure Portal in the Easy Tables section
    • Manually create the table in SQL Server

    I would say the preferred way to create the table is by creating the appropriate files in the tables folder.  The node.js back-end will create new SQL table for any .js file you add to the tables folder (assuming the appropriate supporting files are present).  For example if you create a file named Event.js, you will get a SQL table called Event.  If you create a file named Contact.js, you will get a SQL table called Contact.  You get the idea.  There is a little bit more to it though.  Let’s look at the steps involved. 

    First, you need to be able to edit the files of your node.js App Service app.   You have several ways to do this.  I recommend setting up a local git repository and pushing files up to your App Service App.  You can configure that along with credentials in the Deployment source setting of your App Service App.  You can find more about setting up the node.js back-end and deployment in this article.  However, you can also just edit the files directly from Easy Tables.  If you already have a table created.  Click on the table and then click the Edit script button to edit the files directly in Visual Studio Online.


    Here you can edit the files directly and they are saved immediately.  I am going to start by create a table to store event information named Event.  That means we need to create a file named event.js.  Here is what the starting file looks like.

    var azureMobileApps = require('azure-mobile-apps');
    var table = azureMobileApps.table();
    module.exports = table;

    According to the documentation that is all that is required to get started with a new table.  Now, you might be wondering where are the column names and types?  Technically, they aren’t required.  You see Easy Tables will create new columns on the fly when you make your first insert.  This is great to try things out but not really what you want to do in a production environment.  So I like to specify my own columns.  You can use types such as string, date, boolean, and number.  More complex types aren’t supported by the API.  To create your columns put them in an object and assign to the columns property of table.  Then be sure and set dynamicSchema to false so that it won’t create new columns on the fly.  Set these values before calling module.exports.

    table.columns = {
    	"title": "string",
    	"start_date": "date",
    	"end_date": "date",
    	"description": "string",
    	"image_url": "string",
    	"cost": "string",
    	"event_type": "string",
    	"send_notification": "boolean"
    table.dynamicSchema = false;

    Don’t worry about creating columns for things like and Id, created and modified dates, or even soft delete.  Easy Tables will create those columns for you automatically.

    Before Easy Tables goes and creates your back-end table, there are a few more steps.  First, you need a corresponding .json file.  In our case it would be Event.json.  This contains some basic properties such as if soft-delete is enabled and whether certain operations require authentication.  I found no documentation whatsoever that said this file was required.  However, in the TodoItem samples out there on git hub the file was always there.  Here is what it looks like.

    {   "softDelete" : true,   "autoIncrement": false,   "read": {     "access": "anonymous"   },   "insert": {     "access": "anonymous"   },   "update": {     "access": "anonymous"   },   "delete": {     "access": "anonymous"   },   "undelete": {     "access": "anonymous"   }

    If you want to authentication to be required, you can change the access for the corresponding operation to “authenticated”.  However, we’ll cover that in a different post.

    At this point, you should see an entry for your new table in the Easy Tables section of the Azure portal.  However, the underlying SQL table does not exist yet.  In fact, it doesn’t get created until you make your first API call to it.  That part took me a while to figure out.  Maybe there is a way to automate it getting created but in my experience it doesn’t happen until then.  There is actually a parameter called seed that will let you put sample data into your table, but I have never successfully gotten it to work.

    Calling the API using JavaScript

    In my example, I am using Apache Cordova.  It’s easy to get started with the Cordova SDK and Azure App Service.  Just add the plugin and create a client object and start querying.  Take a look at this post for more details.  If you are using straight HTML / JavaScript, the code is basically the same as well.  First, create a client object using the URL to your App Service.  You can get this from the Azure Portal.

    var client = new WindowsAzure.MobileServiceClient(azureMobileClientUrl);

    Now, we can call getTable with the table name to get the event.  Selecting data from the table is easy, just call .read() to get everything.  It has a promise attached so that you can work with your results and errors accordingly.

    var table = client.getTable('event');
    .then(function (events) {
    	// do something with events
    }, function (error) {
    	// do somethign with errors

    If you want to filter your data just add a where clause.  Each item you add to the collection will be treated as an “AND” operator.  Note, that it is only simple equal comparisons though.

    var table = client.getTable('event');
    return table
    	.where({ id: myId})
    .then(function (events) {
    	// do something with events
    }, function (error) {
    	// do somethign with errors

    You can also use .orderBy() to control the order of the data as well.  It can be used in conjunction with the where clause if desired.

    var table = client.getTable('event');
    return table
    .then(function (events) {
    	// do something with events
    }, function (error) {
    	// do somethign with errors

    Making any of the above calls is enough to get your table created.  You can then go to Server Explorer –> Azure –> SQL Databases and verify that the table was created.  This is a great way to look and see what data is there as well.

    Have a look at the SDK reference for inserting and updating data.  You simply need to create an option with the matching column names and specify the values and call .insert() or .update() accordingly.  Remember you don’t need to specify values for the Id or any of the other fields Easy Table creates.  The response you get back will be the inserted or updated data.

    var table = client.getTable('event');
    return table.insert({
    	title: 'Event Title',
    	description: 'This is an event description',
    	start_date: new Date(),
    	end_date: new Date(),
    	event_type: 'Special Event',
    	send_notification: true
    	.then(function (response) {
    	}, function (error) {

    If you need to delete data, the one thing I ran into is that it only works with the Id field.  If you try to delete based on some other value, you’ll get an error.  If you need to delete based on some other field, you will need to create your own API.  We’ll cover that in another post.

    var table = client.getTable('event');
    table.del({ id: id })
    .then(function () {
    	// deleted
    }, function (error) {
    	// error

    Mobile Apps in Azure App Service is an evolution of Azure Mobile Services.  I often find there is more documentation on that since it’s been around longer.  For example, take a look at this article on working with mobile data as it has a lot more examples.


    Azure App Service Easy Tables make it super easy to get started creating a back-end for your mobile app.  Give them a try and see what you can create.  If you are looking for some samples, be sure and check out the Azure Mobile Apps repository in GitHub.

  • Complete list of Office 365 Connectors for Groups

    Office 365 Connectors for Groups provide a way to pull in information from various sources such as Twitter, GitHub, UserVoice, and Trello.  Office 365 Connectors deliver external content straight to the inbox of your Office 365 Group.  Last fall, I talked about how to use Office 365 Connectors while they were in preview.  However, now they are available for customers with tenants in First Release. 

    Now, there are over 50 Office 365 Connectors available.  Many for services I have never heard of (maybe you have).  Here is the complete list (as of now):

    • Aha! – Manage work with a visual roadmap.
    • Airbrake – Captures errors and aggregates the results for developer review.
    • Alerts by MarketSpace – Company monitoring for marketing, PR, development and investment teams.
    • AppSignal – Track throughput, response times, and error rates in your apps.
    • Asana – Task and Project Management.
    • BeanStalk – A code hosting workflow
    • Bing News – Search news for your work and personalize email update.
    • BitBucket – Manage and collaborate on your code projects.
    • Biztera – Biztera simplifies decision-making with cloud software that streamlines approval workflows
    • BMC TrueSight Pulse (Boundary) – Monitor cloud and server infrastructure with real-time visibility.
    • Brandfolder – Gain great controls of your brand assets, all from Office 365.
    • Bugsnap – Track issues for your web and mobile apps.
    • Buildkite – Smart automation for your software development processes
    • Caller Zen – Create an SMS call center in seconds.
    • Chatra – Modern Live Chat Software.
    • CircleCl – Build, test, and deploy software continuously.
    • Clearlogin – Integrate Clearlogin with your GroupMail to receive real time notifications about use activity.
    • Cloud 66 – Build, deploy, and manage applications.
    • Codeship – Automate the workflow for development and deployment.
    • Crashlytics – Track errors in mobile apps.
    • Datadog – for Dynamics CRM
    • Delighted – The fastest way to gather actionable feedback from your customers.
    • Dynamics CRM Online – Manager your customer sales, marketing, and service relationships.
    • Enchant – Provide customer support with chat and email.
    • Envoy – The new standard for visitor registration
    • GhostInspector – Build or record automated testes for your web site.
    • GitHub – Manage and collaborate on code projects.
    • GoSquared – Simple, yet powerful analytics for your online business
    • Groove – Provide customer support with tem collaboration.
    • HelpScout – Provide customer support through email messages.
    • Heroku – Build and run applications in the cloud.
    • HoneyBadger – Exception and uptime monitoring for your web apps
    • Incoming Webhook – Send data from a service to your Office 365 group in real time (this is how you can bring in your own data to Office 365 groups)
    • IQBoxy – Intelligent Expense Management with Real-Time Receipt Processing and Expense Reports
    • JIRA – Gather, organize, and assign issues detected in your software.
    • JustReply – Simple time tracking for teams.
    • Librato – Real-Time Cloud Monitoring
    • Logentries – Search and monitor log data from any environment.
    • Magnum Cl – Build, test, and deploy software continuously.
    • MailChimp – Email marketing service
    • MeisterTask – An intuitive task management and collaboration tool for agile projects
    • OpsGenie – Alert and Notification solution
    • PagerDuty – Track and manage incidents, and define escalation policies.
    • Papertrail – Track and manage incidents and downtime issues.
    • Pingdom – Track uptime/downtime and performance of web sites.
    • Pivotal Tracker – Track progress in agile projects.
    • Raygun – Monitor crashes in web and mobile apps.
    • RSS – Get RSS feeds for your group.
    • Runscope – Log, monitor, and measure your API usage.
    • Salesforce – Manage sales opportunities
    • Sentry – Capture and aggregate exceptions in code.
    • Stack Overflow – Follow tagged questions and provide answers.
    • – Statues page for App or Website
    • Subversion – An open-source revision control system
    • TestFairy – Test mobile apps and retrace events that precipitate errors.
    • Travis Cl – Run tests and deploy apps.
    • Trello – Manage to-do lists and tasks all in one place.
    • Twitter – Received messages called Tweets.
    • UserLike – Provide live chat support for web sites and mobile apps.
    • UserVoice – Product management and customer support tool.
    • WakaTime – Get updates about your team’s daily coding activity from GitHub, GitLab, or Bitbucket.
    • Wunderlist – Organize and share your to-do lists.
    • Yo – Communicate with others in simple fashion.
    • Zendesk – Zendesk brings companies and their customers closer together.
    • ZootRock – Curated Content in your niche to share to your Groups.

    As you can see that is quite a list of Office 365 Connectors.  Are there any in that list that you will find useful?  Is there anything you wish was on the list?

  • 10 tips a consultant can give to a company issuing an RFP

    In my days, I have seen a lot of RFPs, RFIs, and RFQs.  I’ve seen RFPs that are simple, complex, small, large, strict, well-executed, and no-so-well-executed. In my experience, there are a lot of things you can do to ensure you get the best possible response.  If you are considering issuing a Request for Proposal (RFP) for your next project, consider the following before issuing your next one.

    1) Set realistic dates

    When you issue an RFP, it takes a heap of time for a consulting firm to mobilize a team, get the right people on the call, and prepare a response.  The more complicated your RFP response requirements are the longer it takes to prepare a response.  I’ve received RFPs which want a turn-around in less than a week.  When this happens, often one or more of the bidding firms will push back on you or simply decline to respond.  This often causes multiple extensions to the RFP deadline which honestly doesn’t make your company look good.  When your RFP process is not organized, it makes me question whether we want to do business with your company.  If you can’t run an RFP without a lot of issues, you may not be able to successfully run a project initiative or pay your invoices on time.

    Also pay attention to the dates you set.  Setting an RFP to be due the day after Christmas or during the Thanksgiving break is not cool.  You don’t want to work on the holidays. Your respondants don’t either.

    2) Don’t ask for references in your RFP response

    When applying for a job, I am not going to give you a list of references before I have even talked to someone at your company.  When responding to an RFP, it’s not any different.  It’s not that we don’t want you to vet us out and know our qualifications.  You have to understand references are difficult.  You are asking for us to ask our previous clients to take time out of their day and talk to you about a project on our behalf.  Chances are you aren’t the only RFP we are responding to at a given time either.  That means that client could be receiving multiple calls.  Think about it.  If you select my firm and we successfully implement your project, are you willing to be a reference for any number of random callers?  I doubt it.  Reference calls need to be scheduled and prepared for in advance.  I can’t just have you calling them blindly.

    Instead of asking for references, ask for qualifications.  If you have questions about the qualification ask the respondant to talk about it when you down-select vendors and go to orals.  At that point, it might be acceptable to ask to set up a reference call.

    3) Don’t require answers to questions that aren’t relevant

    You know what makes vendors question if they even want to respond to your RFP?  Required responses to a bunch of questions that aren’t relevant.  I once had an RFP for an Office 365 implementation ask questions such as “Does your product included printed manuals?”.  My response: “We plan on documenting your implementation.  We can print if off for you if you would like.” In the question period, I even asked about these irrelevant questions and the company insisted they all should be completed.  Make sure you are asking the right questions.

    Don’t ask too many questions either.  Keep in mind, that every vendor you pull in is going to mobilize a team of people to put together a response.  This likely includes time from the account manager, a vice president or two, an architect, and maybe an offshore team.  It’s not uncommon for the team to spend several hundred hours combined in their response.  For smaller companies that often means using resources such as the architect that are billable.  For that person they either are billing less or working overtime

    4) Respond to questions in a timely manner

    Potential vendors ask you questions to clarify their understanding of your needs.  Your answers are often crtiical to building their response.  If you don’t reply to answers until two days before the RFP is due, that is going to strain the respondants.  It also means you might not be getting the best response possible out of your bidders because they didn’t have adequate time to prepare it.  Try to get your responses back at leaast a week before the RFP is due.

    5) Stop asking for fixed-bid

    So the project you are working on is risky with a lot of unknowns?  Great, let’s slap a fixed-bid requirements on to the RFP.  That way if there is an issue, you can blame the consultants! 

    Do you not realize what happens when you do this?  You are automatically paying 20% more at the minimum.  The winning firm is going to do everything they can to lock in scope and assumptions so they don’t end up losing money on the deal.  Not to mention, that there is rarely enough detail in terms of requirements in the RFP itself to make an accurate estimation.

    If for whatever reason the consultant can deliver on the fixed bid, eventually you are going to hit a point where you are straining the relationship with your consulting firm.  This is when talks of lawyers come in and then neither of you want to do business with each other ever again.

    Your best bet is to fixed bid a scoping engagement to properly map out the requirements and technical design.  From there, you can get a more accurate estimate on the implementation and you will likely end up paying less.

    6) Don’t include too many vendors

    Keep the number of vendors down to a minimum.  Keep in mind, you are asking a lot of people to jump through a lot of hoops at every firm you contact.  You’re just creating more responses that your RFP team has to read through and rank.  They will all start to look the same after a while too.  Definitely, don’t let one more vendor in because some sales rep got wind late in the process that you were having an RFP.

    7) Stop asking for active and past litigation

    Are the lawyers at your company going to provide a list of all law suits you have ever been involved in to someone random?  Why do you expect us to?  Companies get sued all the time, especially the larger ones.  I don’t see many firms providing you this information.  If you really want the details, you can go dig it up.

    8) Don’t be so picky about the response format

    I think it’s ok to ask respondants to limit the length of their respose to X amount of pages.  It’s not cool to have phrases like “adding a column to this spreadsheet is grounds for being kicked out of the RFP process”.  I understand you have to review multiple RFPs and you are trying to keep things consistent but specifying which font or a maximum file size of an exhibit is just silly. 

    9) Don’t ask for hard copies

    I’m looking at you government and health care companies.  In this day and age asking for a hard copy to be delivered in person or by courier is just silly.  Why don’t you just have us chisel it out the response in stone tablets?  Let us deliver the response electronically via e-mail or through and RFP response portal.  If you just want to print it out because you want to scribble notes on the paper, may I introudce you to the Surface Pro 4.  You can use digital ink to mark up or highlight the response as needed.  If you really do need paper copies, print it out yourself as needed.  Are you just trying to save on printing costs?  If you are that might be a bad sign you don’t need to do this project. 

    10) Don’t issue an RFP if you are just going to pick the encombant

    Again, be mindful of all of the time you are using of people.  RFPs often require sizable teams and late hours to meet the deadline.  If you know you are going to pick the encombant before even starting the RFP process, that is absolutely bad form.  There is a special place in hell for companies that issue an RFP and then just pick the vendor they already had.  Work out whatever issue you had with your vendor and just go with them and skip the RFP process.  If it is procurement pushing you to issue an RFP so that you will get the “best deal”, time to get a new procurement department. :)  At least, let the respondants know that there is an encombant at play.

    Bonus Tip – Don’t ask for names of resources

    Don’t ask for the names of resources that will be staffed in your RFP response.  Do you really think we have an entire project team sitting around on the bench just waiting to be staffed on your project if we happen to win it?  Our company wouldn’t be in business long if we did.  Keep in mind you aren’t the only RFP we are responding to at a given time.  If you really thought we had resoures lying around at all times multiply that by the number of active RFPs and that’s a lot of people not bringing in revenue.  Nothing shows that your company has no idea how the consulting industry works more by asking for the names of resources in an RFP response.  I can almost assure you that whomever we list as a name won’t be the person you get at the start of an engagement.  If you want to know the background of the people you are staffing wait until you select a vendor and then ask for a profile.

    Do you really need to do an RFP?

    You have smart people at your company, but maybe you just don’t have enough of them.  That’s why you are issuing an RFP right?  Maybe you are looking for a certain skillset you don’t currently have?  Before opening up an RFP for your next project, ask if you really should.  Your smart people should already have established relationships with a handful of vendors.  Call some of them, tell them what you are trying to accomplish and just ask for a proposal.  Setting up an entire RFP process is long and overly complicated.  If you already have an established relationship with a few vendors, why shop it out?  If they have done good work in the past, they probably will in the future as well.  If anything you know what you are dealing with.  Do you really want to go with a different vendor for every project just so you can ensure you get the best price?  I understand there are other reasonse to issue an RFP, but you really have to ask yourselfif it’s really worth it?

    Posted Feb 12 2016, 10:21 AM by CoreyRoth with 1 comment(s)
    Filed under:
  • Stalking your favorite celebrities with Office 365 Connectors for Groups

    Office 365 Connectors are a new extensibility point for Groups.  They provide a way to pull in information from various sources such as Twitter, Bing News, and Trello.  The information they provide will be dumped right into your group’s inbox.

    Office 365 Connectors for Groups are new.  Really new.  So new in fact that you have to enable them with a special query string parameter, EnableConnectorDevPreview=true.  The easiest way to enable them is to go the URL below.

    When you go to the URL below, you’ll see a new option for Connectors under the … menu of your group.


    There, you will see a list of all connectors currently available.  This includes things like Bing News, Twitter, JIRA, RSS, Trello, Github, and a few others.


    Since we are looking to stalk celebrities, we’ll make use of the Twitter and Bing News connectors.  I want to know any time, the celebrities I am stalking send a tweet out.  When they do tweet something, what they say will automatically be delivered to my Group’s inbox.  If you are subscribed to the Group the will end up in your inbox as well.

    Let’s add the Twitter connector.  The first thing you will need to do is add an account if you haven’t provided one yet.  Sign-in with your credentials to proceed.


    Now, let’s configure the celebrities we want to stalk.  By adding their twitter handles (minus the @) separated by commas.  You can only enter up to 50 characters in the box, so if you have lots of people to stalk, you can just add another instance of the Twitter connector.


    You can also Track hashtags this way as well as mentions and retweets.  It’s fairly versatile.  When you are done, click the Save button.  When you click it, it will give you no response and just wait there for a few seconds.  Remember this is a developer preview.  If you click it multiple times, you will end up getting multiple connectors, so just be patient. 

    Now, I want to see whatever they say in the news about my celebrities so I am going to add a Bing News Connector.  This will give you a digest once a day of whatever terms you ask it to search on.  Here I have used the Bing News Connector to send me the latest on Neil Patrick Harris.


    Once you are done adding connectors, you can see the ones you added on the Connectors page.  You can reconfigure them here as needed as well. 


    When you return to your group inbox, there will be notifications that your connectors are active.


    Now, you just wait until your celebrities make their move (and for the connectors to fire).  When I first configured them last week, they didn’t work.  Remember, we are in a developer preview.  They are started working yesterday and the data started coming in bulk (and so did the notifications).  In my experience today, the twitter connector usually delivers tweets within 5 minutes of when it occurred.  The Bing News connector delivers a digest whenever it feels like.  I’m not really sure what time zone it is executing in but I assume it’s the local one.

    After your connectors have started providing data, here is what it looks like.  For example, here is the twitter connector providing Wil Wheaton’s latest tweet.  You’ll get one entry in the inbox for each tweet.  The formatting of URLs, usernames, and hashtags could use some improvement, but all of the information is there.


    Here is what the results look like in Outlook 2016.


    It’s up to the connector to provide the formatting, so you can see the results from Bing look a bit different.


    All kidding aside, I hope you can see the power of Office 365 Connectors.  Instead of stalking celebrities, you could use this same technique to quickly provide information about company’s competitors right to your inbox.  There is also a developer story using Webhooks.  The last I checked the URL it provided me didn’t work yet, but we can expect it is coming soon.  Office 365 Connectors are powerful and I am looking forward to using them more.

    I hope you found this look at Office 365 Connectors useful.  Happy stalking!

    Stalk me on twitter: @coreyroth.

  • Drag and Drop into Office 365 comes to Edge on Windows 10

    Looking back to the SharePoint 2013 launch, drag and drop into a document library was one of the hit features.  As many of us have transitioned to Office 365, it’s a feature we expect to be there in our document libraries and OneDrive.  However, when Windows 10 was released at the end of July, the feature was noticeably missing from Microsoft’s newest browser, Edge.  Drag and drop support didn’t work in Office 365, OneDrive, or anywhere else for that matter.

    With the Threshold 2 (TH2) fall update for Windows 10 last week, we now have drag and drop support.  For Windows Insiders, this support has been there in preview builds for a while but it hasn’t been talked about much.


    Say what you want about Edge, I have had pretty good luck with it.  Some people act like it is completely unusable, but I can get most of my day to day tasks done with it.  I’ve used it to replace Google Chrome for almost all of my tasks.  Does it still have issues and does it still need more features?  Absolutely, but it gets the job done for the most part.  If you have discounted it before, give it another try.  It’s constantly being updated.

    One cool feature that came with the fall update is the ability to cast media to a device directly from Edge.  What this means is that when you visit a page with a video on it, you can select cast to device in the menu and choose any Miracast or DLNA supported device to view that content on the remote screen. 

    If you’re not familiar with Miracast, it lets your wireless transmit what’s on your screen to a TV or monitor.  This is included in a lot of devices now such as the Roku.  You can also pick up a Microsoft Wireless Display Adapter as well.  What’s nice is that you can cast a video to a TV from your Windows 10 device and you can still use it while the video is showing.  With Miracast support before, you had to project your entire desktop or extend it just like you did with an external monitor.


    I think it’s a useful feature.  Similar to what Chromecast has been doing for some time now.  However, Miracast is a more open standard and supported across a variety of devices.  The nice thing is that it doesn’t require any additional drivers, plugins, or software to make it work.

  • SharePoint 2016 installation first look

    Today Microsoft released the IT Preview of SharePoint 2016.  We’re going to look at the install process today and point out any differences between previous versions of SharePoint.  You can find out more about SharePoint 2016 from the Office blog post.


    I created a new virtual machine running on Windows 10 Hyper-V.  This virtual machine is running Windows Server 2016 Technical Preview 3.  On this server, I have promoted it to a domain controller using Active Directory Directory Services.  I have also installed SQL Server 2014 R2.

    Installation of SharePoint 2016 IT Preview looks similar to previous SharePoint installations.  When you mount the ISO, you will see a familiar splash screen.


    Installing the prerequisites

    The prerequisite installer looks similar to previous versions.  Click Next to continue.


    Accept the license terms.


    Wait and home it finishes successfully.


    Installation of the SharePoint 2016 IT Preview prerequisites is just as troublesome as previous versions.  I managed to generate a few errors and never did get it to agree the role was successfully installed.  I had to install the Visual Studio 2013 Redistributable myself.  There is a work-around for getting around the IIS role configuration step on the Known Issues in SharePoint Server 2016 Preview page.


    SharePoint 2016 Installation

    The installation is quick and easy.  It also looks similar to other versions.  Start by entering the product key.  Remember this was found on the SharePoint 2016 download page.


    Next, accept some more license terms.


    Specify the install location for your search index.  You can just use the defaults for this preview installation.


    Wait for the installation to complete.


    When installation completes, you will be prompted to run the Configuration Wizard.


    Running the Configuration Wizard

    The Configuration Wizard also looks similar but has a few changes.  Click Next to proceed.


    Now, create a new farm.


    Then, specify your farm passphrase.


    Specify your farm account, SQL Server name and database.


    This new screen allows you use the new MinRole feature. MinRole simplifies the server architecture of SharePoint 2016.  In this case, we are going to use a Single Server Farm (which shouldn’t be as bad as previous versions).


    Specify the details for Central Administration.


    Confirm your settings.


    When it finishes, you are ready to try out Central Administration.


    Now, we can start our configuration.


    That’s a quick look at the installation process of SharePoint 2016 IT Preview.  Be on the look out for my next posts covering changes in Central Administration and the UI.

    Follow me on twitter: @coreyroth

  • How to: Play an Office 365 Video from a Universal Windows App in Windows 10

    I’ve had a personal interest in figuring out how to play videos from the Office 365 Video Portal in a Univeral Windows App (UWP) in Windows 10 since Microsoft Ignite.  In reality, the process isn’t that difficult, but there wasn’t a lot of details out there on how to put the pieces together until recently.  Today, I am going to walk you through how to retrieve the first video in a channel and play it using a MediaElement

    Today, I combined elements I learned from Richard DiZerga’s Universal App blog post, Chakkradeep Chandran’s Ignite session, as well as Andrew Connell's MVC Sample.  Special thanks to all of them for having the pieces I needed to put all of this together.  Since this is a Universal app it should work across multiple devices in theory.

    This app could easily be extended to create a nice interface to browse a channel and pick a video.  If you’re familiar with data binding in WPF though that shouldn’t be hard for you, so I won’t cover that today.  We’re simply going to look at the necessary API and REST calls to get the secure playback URL.  Once we have that URL, we can have the MediaElement start playing the video.

    Getting started

    First, you’ll need to have installed Windows 10 as well as the final version of Visual Studio 2015.  We’re also assuming you have an Office 365 tenant, the Video Portal turned on, and you have some videos uploaded.  If you have never created a Universal Windows App before you can find it under your favorite programming language –> Windows –> Universal –> Blank App (Universal Windows).


    Playing a video from the Office 365 Video Portal involves several steps.  If you know some of the values already along the way (such as the Video Portal URL), you can skip some steps.  I am going to include all of them (which means this blog post is going to be long).  The steps we need to go through are:

    1. Authenticate with Azure Active Directory / Office 365
    2. Access the Discovery Service to get the RootSite ServiceResourceId
    3. Determine the Video Portal Hub Url (i.e.:
    4. Get the list of channels
    5. Get the videos inside a channel
    6. Get the video playback URL

    As you can see, that’s a lot of service calls.  Caching is a good thing.

    Connecting to Office 365

    There are no shortage of ways to authenticate with Office 365 and Azure Active Directory.  Windows 10 introduces a new way called the Web Account Provider.  This will provide us our token that we can pass to the Discovery Service as well as give us tokens to other services such as SharePoint or Outlook.  It will prompt the user to enter his or her credentials if we don’t have a token yet as well.

    To connect to Office 365 bring up the context menu on the project in Solution Explorer and choose Add –> Connected Service.  Select Office 365 APIs and then click Configure.


    The nice thing about the Connected Service dialog in Visual Studio 2015 now is that it takes care of all of the manual Azure Active Directory application setup.  You don’t need to go manually copy a ClientId, secret, permissions, or anything.  This makes the new developer experience much better.

    Now, you need to specify the domain of your tenant (i.e.:


    Clicking Next will prompt you for authentication.  Enter your Office 365 credentials and then you can proceed to the next step.


    Now, we need to tell Visual Studio to Create a new Azure AD application to access Office 365 API services.  This will register the new application in Azure AD and then we can request permissions.


    On the next six steps of the Wizard, we set the permissions that the app requires.  For the purpose of playing a video, we don’t need access to Calendar, Contacts, Mail, or My Files.  For Sites, we need the following permissions:

    • Read and write items and lists in all site collections
    • Read and write items in all site collections
    • Read items in all site collections


    For Users and Groups, select the following permissions:

    • Sign you in and read your profile


    Finally, hit Finish and Visual Studio will add the connected service to your project.

    Designing the Page Layout

    Now we’ll edit MainPage.xaml and add our controls to it.  I kept this simple by just adding a Button control and a MediaElement.  You can arrange them as you like.


    Authenticating with Web Account Manager

    Before we get too far, I am going to create a folder for the Models.  I am going to skip a formal Controller class today since we’re not doing any real data binding.  Normally you would have multiple controllers to pull up a list of channels, videos, etc.  We’ll use a repository class, VideoRepository, that will connect to Office 365 and retrieve our data and our models we’ll use to deserialize the jSon that comes back from the REST API. 

    The VideoRepository class will also handle authentication.  We’ll add the following using statements.

    using System.Net.Http;

    using System.Net.Http.Headers;

    using Microsoft.Office365.Discovery;

    using Microsoft.Office365.SharePoint.CoreServices;

    using Windows.Security.Authentication.Web.Core;

    using Windows.Security.Credentials;

    using Newtonsoft.Json;

    The first method we will create is GetAccessTokenForResource.  If you have looked at other Universal App Samples, this should look fairly similar.  The purpose of this method is to attempt to get a token silently (without prompting the user).  If it can’t, then it it will show the the Office 365 login and the user can login which will provide the token. 

    public async Task<string> GetAccessTokenForResource(string resource)


        string token = null;


        //first try to get the token silently

        WebAccountProvider aadAccountProvider

            = await WebAuthenticationCoreManager.FindAccountProviderAsync("");

        WebTokenRequest webTokenRequest

            = new WebTokenRequest(aadAccountProvider, String.Empty, App.Current.Resources["ida:ClientID"].ToString(), WebTokenRequestPromptType.Default);

        webTokenRequest.Properties.Add("authority", "");

        webTokenRequest.Properties.Add("resource", resource);

        WebTokenRequestResult webTokenRequestResult

            = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(webTokenRequest);

        if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.Success)


            WebTokenResponse webTokenResponse = webTokenRequestResult.ResponseData[0];

            token = webTokenResponse.Token;


        else if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.UserInteractionRequired)


            //get token through prompt


                = new WebTokenRequest(aadAccountProvider, String.Empty, App.Current.Resources["ida:ClientID"].ToString(), WebTokenRequestPromptType.ForceAuthentication);

            webTokenRequest.Properties.Add("authority", "");

            webTokenRequest.Properties.Add("resource", resource);


                = await WebAuthenticationCoreManager.RequestTokenAsync(webTokenRequest);

            if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.Success)


                WebTokenResponse webTokenResponse = webTokenRequestResult.ResponseData[0];

                token = webTokenResponse.Token;




        return token;


    Let’s look at some of the highlights.  First we get our aadAccountProvider by calling WebAuthenticationCoreManager.FindAccountProviderAync().  This is the call into the Web Account Manager that I have been talking about.  You always pass it the (at least for this exercise).  We then need a WebTokenRequest.  This is where the ClientId of the application comes in.  Remember Visual Studio created this for us when it registered our app with Azure Active Directory.  The resource property is where we pass in the Uri to the service we want to access.  On our first call this will be the Uri of the discovery service.  On subsequent calls it will be the Uri we get for accessing things in SharePoint.

    Next, the method tries to silently authenticate the user.  This method would return with a Success result if the user has authenticated inside this application before. 

    WebTokenRequestResult webTokenRequestResult

        = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(webTokenRequest);

    If the user already has a token, then we are done.  Otherwise user interaction is required. The RequestTokenAsync call on the WebAuthenticationCoreManager is what actually prompts the user for credentials.  Ultimately, this method returns a token for the resource you asked for.  When we run the application and click the Play button, it will prompt us for credentials.


    After you authenticate, you will get prompted to grant permissions to the app.  These will match the ones we specified earlier when adding the Connected Service.


    Calling the Discovery Service

    We’re going to call the Discovery Service to determine the ServiceEndpointUri for the RootSite capability. We’ll do this in a new method called GetSharePointServiceEndpointUri. We do this by accessing for an access token from our GetAccessTokenForResource passing the URL

    string accessToken

        = await GetAccessTokenForResource("");

    DiscoveryClient discoveryClient = new DiscoveryClient(() =>


        return accessToken;


    After we get a DiscoveryClient, we can call DiscoverCapabilityAsync.  This method also stores the access token used for accessing resources in the variable sharePointAccessToken.  It also stores the ServiceEndpointUri in the variable sharePointServiceEndpointUri.  We’ll use this URI for the subsequent REST calls.

    CapabilityDiscoveryResult result = await discoveryClient.DiscoverCapabilityAsync("RootSite");

    sharePointAccessToken = await GetAccessTokenForResource(result.ServiceResourceId);

    sharePointServiceEndpointUri = result.ServiceEndpointUri.ToString();


    return sharePointServiceEndpointUri;

    Remember, the full source code is available in GitHub.

    Get the Video Portal Hub URL

    If you have worked with Office 365, you probably know that it’s pretty easy to guess what the URL to the Video Portal Hub will be (the hub is the root site collection of the Video Portal).  Since we want to do things right though, we’ll go through the Video Service’s Discover endpoint to determine the URL.  In fact, once we construct these next two methods, the rest will be very similar.

    We’ll create a new method called GetVideoPortalHubUrl.  The first thing we’ll do is call GetSharePointServiceEndpointUri to authenticate and return us the endpoint for working with SharePoint.  We append VideoService.Discover to the Uri returned by our method.  How did we know this was the URL, it’s in the Video REST API reference (still in preview).

    var requestUrl = String.Format("{0}/VideoService.Discover", await GetSharePointServiceEndpointUri());

    We then, create a function that returns an HttpRequestMessage using the requestUrl.

    Func<HttpRequestMessage> requestCreator = () =>


        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);

        request.Headers.Add("Accept", "application/json;odata=verbose");

        return request;


    Then, we create a new httpClient and pass it, our access token, the HttpClient, and the RequestMessage to a custom method we will build named SendRequestAsync.   This piece is based upon other’s code so I didn’t really tweak it since it works.  After our call to that method, we’ll deserialize the jSon that comes back.  I borrowed several of AC’s helper classes from his MVP example here.

    Let’s take a look at SendRequestAsync.  We’ll start with a using blog to get our HttpRequestMessage

    using (var request = requestCreator.Invoke())

    We’ll then need to add the necessary headers.  First, we add an AuthenticationHeaderValue with the sharePointAccessToken we got earlier.  We also add another header, X-ClientService-ClientTag.  I don’t know if this is required but Chaks included it in his examples.  I updated the version to match the current version reported in the Connected Service wizard.

    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    request.Headers.Add("X-ClientService-ClientTag", "Office 365 API Tools 1.5");

    Then we invoke the request using httpClient.

    var response = await httpClient.SendAsync(request);

    The method then returns the response assuming it’s successful.  The example that Chaks provided will actually make a second attempt to call the service if the user isn’t authorized.  You can optionally include that if you like.

    Now going back to our GetVideoHubUrl method after we successfully got a response back.  We now need to parse the JSON that came back into a usable object.  This is where Newtonsoft.Json comes in.  We use the models that AC provided in the MVC project. In this case we serialize the responseString into an object of VideoServiceDiscovery.  Now, we can get the VideoPortalUrl for our subsequent REST calls.

    string responseString = await response.Content.ReadAsStringAsync();

    var jsonResponse = JsonConvert.DeserializeObject<VideoServiceDiscovery>(responseString);

    videoPortalUrl = jsonResponse.Data.VideoPortalUrl;

    Get the video portal channels

    Now that we have our Video Portal Hub URL, we can retrieve the list of channels.  The Video REST API Reference tells us we need to append /_api/VideoService/Channels to the Video Portal Hub URL which we just retrieved.  We’ll create a new method called GetVideoChannels which will look similar to GetVideoPortalHubUrl expect the requestUrl used and the JSON serialization.

    var requestUrl = string.Format("{0}/_api/VideoService/Channels", videoPortalUrl);

    Since we return multiple channels, we loop through the results and add new VideoChannel objects to the list. 

    string responseString = await response.Content.ReadAsStringAsync();

    var jsonResponse = JsonConvert.DeserializeObject<VideoChannelCollection>(responseString);


    var channels = new List<VideoChannel>();


    foreach (var videoChannel in jsonResponse.Data.Results)


        var channel = new VideoChannel


            Id = videoChannel.Id,

            HtmlColor = videoChannel.TileHtmlColor,

            Title = videoChannel.Title,

            Description = videoChannel.Description,

            ServerRelativeUrl = videoChannel.ServerRelativeUrl




    At this point, you have enough data you can start doing some data binding.  As I mentioned earlier, I am skipping that since data binding in a Universal Windows App for Windows 10 is quite similar to what was there in Windows 8.1  For our example, I am simply going to pass the Channel Id into our next method to retrieve a list of videos.

    Getting the list of videos in a channel

    Now that we have a list of Channels, we can make another Video REST API call to get a list of videos in our new method GetVideos.  We build our requestUrl by appending /_api/VideoService/Channels(‘<channelid>’)/Videos.  Remember we got the Channel Id from our last API call.  Now this simply returns the metadata about the video.  After this, we still have one more call to get the Playback URL.

    var requestUrl = string.Format("{0}/_api/VideoService/Channels('{1}')/Videos", videoPortalHubUrl, channelId);

    The rest of the method is similar to GetVideoChannels

    Get the video playback URL

    For the purpose of our example, we’re also going to simply play the first Video in the Channel.  To get the Playback URL, we’ll need the Video Id as well as the Channel Id we retrieved earlier.  When it comes to streaming, we have a choice of either Smooth Streaming or HLS Streaming by specifying the streamingFormatType parameter on the Video REST API call.  HLS streaming requires one fewer API call so we are going to use that for the example today.  You may want to use Smooth Streaming for your application.  To use HLS Streaming, specify a value of 0.

    var requestUrl = string.Format("{0}/_api/VideoService/Channels('{1}')/Videos('{2}')/GetPlaybackUrl('{3}')",

        new string[] { videoPortalHubUrl, channelId, videoId, streamingFormatType.ToString() });

    The REST call will return a playback URL which we can then assign to the MediaElement

    Playing the video

    On the click handler of the Play button we added in the beginning, we make our calls into the VideoRepository class.  Once we get the Playback URL we binding it to the MediaElement and the video will start playing.  I also set a few parameters to turn on the transport controls and enable full screen mode.  You can set those as you like.

    private async void button_Click(object sender, RoutedEventArgs e)


        VideoRepository videoRepository = new VideoRepository();

        string videoPortalUrl = await videoRepository.GetVideoPortalHubUrl();

        var videoChannels = await videoRepository.GetVideoChannels();

        string channelId = videoChannels[0].Id;

        var videos = await videoRepository.GetVideos(channelId);

        string videoId = videos[0].VideoId;

        var videoPlayback = await videoRepository.GetVideoPlayback(channelId, videoId, 0);


        mediaElement.Volume = 0;

        mediaElement.AreTransportControlsEnabled = true;

        mediaElement.IsFullWindow = true;

        mediaElement.Source = new Uri(videoPlayback.Value);


    There you have it a (somewhat) quick and dirty way to play a video from the Office 365 Video Portal in Windows 10.  This should work on Windows 10 Mobile as well.  Here is what our app looks like when playing a video.


    Source Code

    As promised the source code is available on GitHub.  I may extend it in the future to include all of the data binding and improve the look.  Feel free to contribute to the repo as well.  If you make use of any of the code, you’ll want to add error handling of course.

    Feel free to ask me any questions by leaving a comment.

    Source code on GitHub

    Follow me on twitter: @coreyroth

  • Moving the blog to Azure and the origin of

    When we built, we used one of the most common blog engines around Community Server by Telligent.  At the time Telligent had a great blogging platform that they provided free to technical bloggers.  They really did a service to the community.  Then one day, they decided to drop the free product and start charging for new versions even for community bloggers.  Now, people barely even remember the name Telligent and for good reason.  Cloud offerings like with their freemium model moved in and took over.

    Moving to Azure

    That said, my blog has been running on a Windows Server 2003 virtual machine with only 2 GB of ram since 2006 or so.  As old as my version of Community Server is now, it still works pretty well.  It did come out before the days of mobile devices so the master page I have could use some work.  It’s been serving up blog posts for years though without issue.

    The virtual machine was hosted with my old employer, Isocentric Networks.  Isocentric is a small data center based in Tulsa, OK.  I learned all about racking, networking, and hosting while I worked there.  They have been nice enough to let me host my blog there all of these years.  I am truly thankful.

    With Window Server 2003 no longer being supported as of last month though, it was time for the blog to move.  I created a new Windows Server 2012 R2 virtual machine in Azure and copied the database and everything over.  I was a little fearful that I might not be able to get Community Server to work in the new environment, but everything worked just fine.  I just created a .NET Framework 2.0 application pool and configured a new web site in IIS and everything worked fine.

    Now, I have pointed the DNS entry for the site over to the Azure Virtual Machine and things seem to be running great.  If you see an issue, feel free to ping me on twitter @coreyroth.

    Why DotNetMafia?

    Over the years, many people have asked why DotNetMafia?  Well as with a lot of great things in life, the concept started while a few of us were sitting around at the bar for happy hour one day.  We were telling stories about how there were some recruiters in town that were less than professional.  Back then it wasn’t uncommon for a recruiter to lie to your face, make you lie on your resume, or just sent it to a client without even talking to you first.  We wanted to build a web site where we could rate recruiters and people could go talk about the good and bad things recruiters did.  So Kyle Kelin (a.k.a. theGodfather), came up with the concept and name.  Like all of the billion dollar ideas, we came up with back then, we only got about as far as purchasing the domain name. 

    A lot of us were changing jobs back then (hence the recruiter thing).  I actually started the blog internally when we were all working at Dollar Thrifty Automotive Group.  .NET Framework 2.0 was in beta and I started it to teach the development team I led about the new features that were coming.  Back then it was simply called Corey’s .NET Tip of the Day.  It really wasn’t a blog though, it was really just an announcements list in SharePoint 2003.  I wasn’t really working with SharePoint much back then, but I thought it was a good tool at the time for what we were trying to accomplish.

    When I left Dollar Thrifty at the end of 2005, I wanted to keep the content going so I moved it to a virtual machine I had at Isocentric Networks and hosted it at  I actually exported the contents of my announcements list into Excel and then imported into a SQL Server database.  I wrote my own custom blogging engine at the time and I used it for a while.

    Now a year or so later, a few of the other ex-employees of Dollar Thrifty wanted a place to blog too.  Tony Kilhoffer set up a SharePoint 2003 server and I tried to use the blog platform there.  Unfortunately, we couldn’t ever get the content quite right so we gave up. 

    Then we ended up with Community Server.  The nice thing about Community Server was it had the ability to import content from an RSS feed.  This made bringing in all of my old content quite easy.  If you look around the blog, you’ll notice we host for six different people: Cory Robinson, Kyle Kelin, James Ashley, Tony Kilhoffer, Kevin Williams, and myself.  None of them really blog much any more, but their content is still there.  We had all of the bloggers, but what were we to call this new site?  A cheesy name that has worked well for us.

    Why not move to a new blogging platform?  I definitely want to but it is a bit of a challenge.  Moving the content to another platform isn’t that difficult.  However, maintaining the existing URLs when moving to a new platform is difficult.  If I don’t maintain them, I’ll break the SEO of the site.  My top post every month is years old and talks about using PowerShell with SharePoint 2010.  The SEO is important so before I migrate anywhere, I need to have a solid solution to maintain those links.

    Posted Aug 04 2015, 01:08 PM by CoreyRoth with no comments
    Filed under:
  • Fixing Office 365 ProPlus Activation Prompts on Windows 10

    If you are using Office 365 to deploy Office 2016 Preview (Office 365 ProPlus) to your desktop, you may have found that you get hit with multiple prompts to activate the product even though it is already activated.  You can click Cancel on the Activation but it will prompt you again when you open up any other Office product.


    @MarioFulan on twitter mentioned that performing an Online Reset corrects this issue.  In Windows 10, you will need to go to the old control panel to launch the repair process (otherwise you’ll just uninstall the product).  Choose Online Repair.


    If you haven’t installed Office 365 ProPlus in a while, they have actually updated it for Windows 10.  When applications are available, you can click the Open button to start using them.


    When the process is done, you’ll notice some new prompts showing you how to launch Office.  It will also pin many of the Office apps to your taskbar.


    Once the process is complete, you shouldn’t be prompted with all of the activation prompts.

  • Working with Office 365 Groups using PowerShell

    New features are coming fast to Office 365 Groups.  As administrators we have been looking for ways to simplify the management of groups.  This includes functions like adding groups, deleting groups, and adding members to groups.  At Ignite last week in session BRK3114 they showed us some of the new PowerShell cmdlets available to make this happen.  There isn’t any documentation on this stuff at all yet, so I wanted to show you some of the stuff that was showed at the conference.

    Establishing a connection to Exchange Online

    Groups are ultimately powered by Exchange (and then SharePoint).  As a result, we make use of the Exchange Online cmdlets.  If you have never used these cmdlets before, we start by creating a session.  Start by opening a PowerShell window of your choice.  We’ll be following the steps provided by TechNet.

    First, get your credentials in PowerShell and store them in a variable using Get-Credential.  A window will pop up prompting you for your credentials.   Use your Office 365 Global Administrator account.

    $userCredential = Get-Credential


    Now, we need to create a session with New-PSSession and pull down the Exchange Online cmdlets.  Executing this command will yield no output.

    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $UserCredential -Authentication Basic -AllowRedirection


    Finally, use Import-PSSession to make the connection.  This takes a few moments as it shows you all of the cmdlets it has loaded.

    Import-PSSession $session


    If you examine the output closely you’ll see some cmdlets for groups in there.  Now we are ready to being working with groups on our tenant.

    Getting a list of all groups

    Let’s start by seeing what groups are present with Get-UnifiedGroup.  Type the following in PowerShell.



    That’s odd.  It returned only one group and I have more than that on my tenant.


    This is because if you have existing groups, they are likely in a state of transition to a new type of object in Azure Active Directory that can be synchronized back to your on-premises Active Directory Domain Services.  This deployment is only temporary though and it may already be working on your tenant.  I created a new one through the user interface today and it showed up.  The one I created months ago did not.

    Creating a new group

    To create a new group with PowerShell, we use the New-UnifiedGroup cmdlet.   Here are the key parameters:

    • DisplayName – display name of the group
    • Alias – alias of the group if you want to override it.  If you omit the parameter, it will generate an alias for you.
    • AccessType – Public or Private
    • AutoSubscribeNewMembers – Add this parameter to auto subscribe new members to the group

    The Members parameter which takes an array of Recipient Ids to add users to the group.  There is also a large number of other parameters that allow you to customize things even further.  I am pretty sure some of these parameters aren’t even configurable in the user interface yet.

    To create a group with minimal parameters, just use the DisplayName parameter:

    New-UnifiedGroup –DisplayName "PowerShell Group 1"


    Unfortunately, since the cmdlets are still under development, this one doesn’t work right now.  However, it might work by the time you try it.

    Adding users to a group

    The cmdlet to add users to a group in PowerShell, Add-UnifiedGroupLinks, actually does work right now.  Here are some of the key parameters:

    • Identity – Alias of the group
    • Links – login or alias of the user being added
    • LinkType – Members, Owners, or Subscribers

    To add a new user to the members group:

    Add-UnifiedGroupLinks groupalias –Links –LinkType Member


    Successful execution will not yield any output.

    To add a new user to the owners group, first add them as a member and then add them as an owner.

    Add-UnifiedGroupLinks groupalias –Links –LinkType Member

    Add-UnifiedGroupLinks groupalias –Links –LinkType Owner


    You can verify that your users are in the group through the Groups user interface.  Note that the user “Joy” is listed as an owner.


    We can also verify the users are in the group via PowerShell.

    Getting the members of a group

    We can use PowerShell to view the members of an existing group with the Get-UnifiedGroupLinks cmdlet.  The key parameters for this cmdlet are:

    • Identity – the alias of the group
    • LinkType – Members, Owners, or Subscribers.  Required.

    To see the members of a group with PowerShell, issue the following command:

    Get-UnifiedGroupLinks –Identity groupalias –LinkType Members


    Removing a user from a group

    You can remove a member from a group using Remove-UnifiedGroupLinks.  Here are the parameters:

    • Identity – alias of the group
    • Links – login or alias of the user to be removed
    • LinkType – Member, Owner, or Subscriber.  Required.

    To remove a user as a member from the group, use the following command:

    Remove-UnifiedGroupLinks groupalias –Links –LinkType Member


    To remove an owner from the group, you will first have to remove he or she from the LinkType Owner.

    Remove-UnifiedGroupLinks groupalias –Links –LinkType Owner

    Remove-UnifiedGroupLinks groupalias –Links –LinkType Member

    Removing a group

    As expected, the cmdlet to remove a group doesn’t function right now either.  We can still look at the syntax though.

    Remove-UnifiedGroup groupalias

    Getting help with the groups cmdlet

    You can type help unifiedgroup to load the help modules for Groups.  When you do, you’ll again get a bunch of verbose information followed by the listing of cmdlets.  Unfortunately, they don’t provide any real documentation yet, but you can see a listing of parameters using get-help.



    This is truly a case where we are getting early access to PowerShell functionality.  While not all of the functionality is ready yet, it’s great to see that we can get started.  Just being able to easily add members to a group using a PowerShell script already is a huge win!  Remember that these cmdlets are highly subject to change right now before you invest a lot of time building scripts around them.  I’ll update this post when the cmdlets are finalized.

    If you want to learn more about working with Groups, be sure and watch Ignite Session BRK3114 where they demonstrate some of these cmdlets in action.

  • Ignite Readiness Checklist

    I started doing SharePoint Conference readiness checklists back at SPC11 and I wanted to continue the tradition with Ignite.   This list may look similar to previous lists, but I have made lots of updates and additions.

    What to pack:

    • Chargers / Power Supplies – I remember when I went to PDC05, I forgot my laptop charger.  I was quite bummed.  Don’t forget the chargers to your laptop, netbook, Surface, phones, etc. I have gotten a few of these new emergency phone chargers at conferences lately and they are very handy here.  Especially when you have a Nokia Lumia 920 and the battery life is terrible.  Keep in mind your average day can be 16 – 18 hours plus and you don’t want to be left in the dark and miss that big gathering because your phone died.
    • Backup power – If any vendors are giving out backup power supplies, grab them!  You know the portable chargers that you can take with you.  We have several of them and they are a life saver.
    • Tablet / Laptop – You’ll want some kind of computer whether that’s a tablet, laptop, hybrid of whatever.  You want something with a keyboard.  This makes it easier to send e-mail or post tweets.  Besides, the more you are on this device, the less you have to rely on your phone and use its power. You also can use these to fill out session evaluations.  There are usually incentives for filling out evaluations so I try to complete each evaluation right before the end of the session so I don’t forget.
    • Bring your own Internet  – The wireless networks at conferences are rarely good.  They are jammed with geeks trying to post updates on Twitter and check out what’s happening on Facebook.  If you have access to a wireless AirCard, MiFi, tethring, etc, bring it.  See if your company has any that you can check out temporarily.  Conference organizers really don’t like you using these during keynotes because the more hotspots you create, the slower the Internet gets.  The slower the Internet gets, the more hotspots people turn on.  It’s a vicious cycle. I'd still bring your one if you can.
    • Cash – There are a lot of free events but you might go do something before or after the conference and I am not a fan of running tabs at busy restaurants and bars.   Don’t take it all with you every night.  Leave some in the hotel safe.
    • Snacks and Water – After a long night, you will want something to eat.  At the minimum, you might want something to eat in the morning.  The hotels will likely have stuff in your room, but it will cost you dearly.
    • Business Cards – Even if you are not in sales, bring twice as many as you think you will need.  You will go through them faster than you think.   It’s amazing how many people forget these at a conference.  Don’t be one of those people!
    • Bail Money – The Houston SharePoint Users Group has a running joke about always keeping a stash of bail money around when attending a #SharePint.  You never know what is going to happen.  0
    • Headset – If you think you are going to have to take any calls during the week, don’t forget your Bluetooth headset.  This will make it easier to do your calls for sure.
    • VPN Tokens - If your work network requires a VPN token or Smart Badge you might want to bring it if you think you might need to use it.  Otherwise, you might conveniently forget it, to ensure you can focus on the conference. :)

    Before you go:

    • Arrive early – Come in early and have some fun in Chicago before you get into the conference grind.  Many of us will be arriving Friday or Saturday.  I tend to arrive on Saturdays while most of the foreign nationals I know, tend to arrive Friday or earlier.
    • Don’t leave early – Normally I say this, but they have extended the conference by a day.  Come Friday, I’ll be ready to be on the first plane out of Chicago.
    • Set your schedule on MyIgnite - This will make your Ignite organizers happy when it comes to capacity planning.  You aren’t required to go to that session you schedule, but it will help you pick from the 10+ sessions going on at any given time slot.  Go to MyMignite and set your schedule now.   Not sure about a session, watch the teaser video on YouTube.
    • Create your Bio on MyIgnite  – Whether you are an end user or a rock star, take a few minutes to write about yourself.  Include where you work if you want along with what you typically do with the Microsoft stack and what you want to get out of the conference.  Upload a picture of yourself to make things more personal.  Be sure and set the privacy settings as desired.  Set your MyIgnite bio now.  Be sure and edit your profile on Yammer too.
    • Connect on MyIgnite - If you go to the Communities tab, you can search for other attendees. 
    • Get on Yammer - The conversations have already begun about Ignite on Yammer.  This is a great way to find out what other people are doing, network with others, and talk with people with similar issues.  Most importantly, you can have a conversation about the sessions while they are occurring.  Speakers will be watching Yammer before, during, and after their sessions.   Be sure and follow others in Yammer to have more show up in your social feed.
    • Create a #msignite Search in Twitter – Twitter hasn't gone away by any means, so keep an eye on the activity of the #msignite hash tag.  However, this year, I think Yammer is where you are going to find the most info and conversations.  Twitter will still be good to find out about sessions, events, and it will generally give you an idea of what is happening at the conference.  Be sure and include the #msignite hash tag on anything you post and help get this conference trending!
    • Follow @MS_Ignite on Twitter – @ms_ignite is the official twitter account for Ignite.  This account often posts useful stuff about the conference.  I’ve also used it to ask questions or provide general feedback and I’ve had very good luck getting a response.  Keep in mind this twitter account is effectively manned by one person, so if you have an inquiry, take it to Yammer.
    • Download the Ignite Mobile App – Whether you use iOS, Android, or you are one of the last few Windows Phone users, be sure and download the Microsoft Ignite App before you go.  Download it now while you still have good Internet!
    • Reach out to your local User Group – Find out what your local User Group is doing while at Ignite.  Many of them are having meetings or socials. 
    • RSVP for Parties – Unfortunately, if you haven’t RSVPed for parties by now, you’re probably out of luck.  However, being persistent can get you in.  Talk to the vendors in the exhibit halls hosting the parties.  Sometimes you can just show up and talk your way in.  Check the Events at Ignite Yammer group.  Also check Vlad’s Ultimate Party List regularly.  Be sure and follow @SPCPartyPatrol to find out where the parties are too!
    • Arrange for Ground Transportation  - Don’t forget to arrange for ground transportation.  You really don’t need a car in Vegas, but you do need a way to get there.  Taking a Taxi usually isn’t too expensive and there are plenty of shuttle options as well.  This may be less of a concern on arrival but more for your departure.
    • Leave space in your bag – Between the conference materials and the vendors you are going to end up with a heap of product information, trinkets, and T-shirts.  Make sure you have room in your bag to bring them home.  Otherwise you’ll be hand carrying them on the plane or leaving things behind.
    • Update your devices - Now is a great time to make sure your devices are up to date with the latest security patches.  Make sure they are charged too!
    • Set your out-of-office - You're at this conference for a variety of reasons, you need to focus.  Try to stay out of Outlook and let people know that you will be slow to respond.  If you need to stay connected, I recommend picking one time of day, such as in the morning before sessions, to catch-up on what's happening back at home.

    What to do at the conference:

    • What happens in Chicago, will not stay in Chicago – Nerds have gadgets and they like to take pictures.  Do something stupid and you can rest assure it will be on twitter within seconds. :)
    • Ask questions  - Don’t be afraid to walk up to the mic and ask a question.  That’s what you’re here for.  If you don’t want to ask it in front of everybody, wait in line and talk to the speaker at the podium just be mindful that the speaker has to clear out in a hurry.  Don’t be afraid to approach speakers outside the room either.  Most of them are friendly and are easily engaged using beer and cocktails. :)  It's not uncommon to find them at the official SharePint bar.
    • Make friends – You may run into lots of people you know, but many people aren’t active on twitter and aren’t familiar with the SharePoint community at all.  Find a friend if you didn’t come to the conference with any one.  It’s much more fun to go do all of the activities in a group rather than by yourself.  If you have coworkers there, feel free to hang out with them, but don't feel that you are obligated to.
    • Go to the evening events - I can't stress this enough.  Try to avoid team dinners that overlap with the events.  Get them rescheduled.  The evening events are where the real connections are made, friends are found, contracts are signed, and new jobs are discovered.  If you just go to the conference and nothing else, you are missing out on half the experience.
    • Remember to eat - This one sounds obvious but it’s not.  You may be going to lots of parties with nothing but light appetizers.  This does not give you a good base to work upon before embarking on a night of massive consumption. Pace yourself!
    • Don’t worry about writing everything down – Remember the slides and content will be on Yammer before the session.  Don’t stress out because you weren’t able to write down a URL or code snippet on a slide.   You can also take pictures of slides as well.
    • Visit the Exhibit Hall – The exhibit hall is a lot of fun.  Besides all of the SWAG and drawings, you are likely to find out about evening events that way. Make a point of going there every day.  I spend a good majority of my time there during the conference.  You'll never know who you run into.
    • Be on the lookout for the SharePoint Monkey – The word on the street is that the SharePoint Monkey will be making an appearance.  You'll never know what that silly monkey is going to be up to during the conference.  Be on the look out for him throughout the convention center.  Follow him on twitter @TheSPMonkey for clues!
    • Attend the sessions – Don’t skip out on the morning sessions.  If I have to get up early so do you. :)
    • Attend the Hands on Labs – If you haven’t had a chance to get your hands on the latest technology, get down to the HOL and check it out.  This is a great way to experience the product without having to take the time to install it.   It opens at 9:00 am on most days (after the keynote on Monday).
    • Take a test – Go roll the dice and find some time to take a test.
    • Don’t underestimate travel times – It’s a long bus ride to the convention center.  It can be between 15 and 30 minutes if not more.  Even within the convention center, there are long walks between sessions.  Plan accordingly.
    • Set your alarm before you go out for the night - Before you go out for the night, set your morning alarm on your phone.  You may not remember when you get back to your room.
    • Arrive early to sessions – Many sessions will fill up and entrance will be denied, especially futures sessions.  Don’t get left out by showing up late.
    • Don't be afraid to leave a session - If you decide in the middle of the session, that this one isn't for you, don't be afraid to quietly step out and go see something else.  A few speakers might call you out for it, but most won't. :)
    • Learn hash tags for the sessions you are attending – Every session you are attending has an associated hash tag that you can follow. 
    • Don’t wear your badge outside of the convention center – Nothing says you don’t have any game like walking out of the convention center with your badge on.  Take it off as you exit the area.  Don't lose it though as it may cost you a lot to replace it.
    • Don’t forget your badge (and lanyard) at the attendee party – You’ll need your badge everywhere you go.  Bring it and the lanyard. 
    • Keep your phone charged – The battery life on LTE phones is horrible and even worse when you are tweeting non-stop all day.  Keep an eye on your phone’s battery life and charge up throughout the day. 
    • Don’t be afraid to leave for lunch – I’m not a huge fan of conference food and it rarely gets along with my diet.  Usually by the second or third day I am grabbing anyone I can find and going off-site.  Find me at the conference and you can join me.
    • Fill out your evaluations – These really are important to the speakers.  Let them know they did a good job and take the time to leave actual text comments in them.
    • Establish rendez-vous points – Establish meeting spots in advance with your group and set a time to meet. 
    • Go to the attendee party – Go to the attendee party.  If you are expecting to meet people there, meet them before you leave the hotel.  If you don’t walk in with the people you want to see, you will likely not see them that night. 
    • Hydrate - Drink lots of water throughout the day.  This is especially important if you have had a lot of late nights.
    • Silence your phone during sessions, turn it on as loud as possible everywhere else - Don't be "that guy" who has your phone ringing in the middle of a session.  That's guaranteed embarrassment. When you're not in sessions, turn the volume up on it as you probably won't hear it go off otherwise when you get a message.

    That’s my list.  I’m sure there are other things to remember.  Do you have anything else to add?  Leave a comment.  This probably goes without saying, but if you are not on Yammer and Twitter, now is the time to join.  It’s the best way to keep up with what’s happening at the conference.

    I’m also presenting a session with Matt McDermott at this year’s conference and we would love for you to come see it.

    • #BRK4124Search Extensibility in SharePoint 2013 (Second Screen) (Thursday, May 7th, 5:00p) – Come on a tour of the common extensibility and development tasks needed to take advantage of the full power of SharePoint 2013 Search Service. Ingest content from external sources through the BCS. Enhance content prior to indexing via Content Enrichment. Pinpoint relevancy and enhance user queries through contextual targeting with Query Rules. Make the most of the new Keyword Query Language improvements. Finally, customize the end-user experience and make your search results shine!

    Enough with the shameless plug. :)  Get ready and I’ll see you at the conference.

    Follow me on twitter: @coreyroth.

  • Display scaling improvements come with Windows 10 Build 10074!

    For those of you out there with a Surface Pro 3 connected to an external monitor, you know the pain of display scaling.  This typically caused a phenomenon where windows were sized normally on your Surface Pro 3 display while being massive on your external monitor.  Most users I have talked to found this absolutely frustrating.  The only real solution was to purchase an external monitor with an equally high DPI.  This meant purchasing a high dollar 4k monitor.  While those displays are nice, most people have plenty of good LCD displays in the 20” – 30” range which are working perfectly fine right now.

    With Build 10074 of Windows 10 Insider Preview, some of this pain goes away.  That’s because of the new ability to set the DPI scaling to an independent setting for each connected display in the new Settings app.  Now, I can set the display scaling to 150% on my Surface Pro 3 display but have my external monitors set to 100%.  Windows is smart and even auto detects the right settings for each. 

    Let’s take a look at this new setting.  The setting Chagne the size of text, apps, and other items is set to 150% (Recommended) on my Surface Pro 3 display.


    On my external monitor running a resolution of 1920x1080, the setting is set to 100%.


    This is great, but how does it perform?  I found that this fixed the issue in a lot of programs including some of the Office suite.  Let’s look at some examples.

    File Explorer on the Surface Pro 3 display:


    File explorer on an external display:


    Notice they are the same relative size!  You’ll actually see windows resize it as you move them as well.

    Word 2016 Preview does pretty well too.  Here it is on the Surface Pro 3 display:


    Word 2016 on the external display:


    File Upload dialogs used to be massive on external displays.  Now they are regular-sized.


    Some programs handled this better than others.  However, PowerPoint and Skype for Business (aka Lync) still have issues.  A typical chat still takes up more a large part of the screen.  Notice the difference in ribbon sizes between Word and PowerPoint.


    The new Microsoft Edge browser (still referred to as Project Spartan in this build) also has some issues as well.  For example, when you launch it on the Surface Pro 3 display, it will set the zoom level to 150%.  However, when you drag it to another monitor, it doesn’t adjust the zoom level automatically.

    There has also been some improvements in other Windows Universal apps so that they scale better on external monitors.  It isn’t perfect yet either but the snapping has definitely improved.

    Surface Pro 3 users have been crying out for improvements here and it’s nice to see that they are in the works.  I hope to see additional improvements as we see new builds.

    Follow me on twitter: @coreyroth

More Posts Next page »
2015 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems