﻿<?xml version="1.0" encoding="UTF-8"?>
<!--RSS generated by Microsoft SharePoint Foundation RSS Generator on 5/18/2013 6:11:00 AM -->
<?xml-stylesheet type="text/xsl" href="/_layouts/RssXslt.aspx?List=e10cb685-6b5c-4b6c-aaf4-e1d122d57174" version="1.0"?>
<rss version="2.0">
  <channel>
    <title>Liam Cleary [SharePoint MVP]: Posts</title>
    <link>http://blog.helloitsliam.com/Lists/Posts/AllPosts.aspx</link>
    <description>RSS feed for the Posts list.</description>
    <lastBuildDate>Sat, 18 May 2013 11:11:00 GMT</lastBuildDate>
    <generator>Microsoft SharePoint Foundation RSS Generator</generator>
    <ttl>60</ttl>
    <language>en-US</language>
    <image>
      <title>Liam Cleary [SharePoint MVP]: Posts</title>
      <url>http://blog.helloitsliam.com/_layouts/images/siteIcon.png</url>
      <link>http://blog.helloitsliam.com/Lists/Posts/AllPosts.aspx</link>
    </image>
    <item>
      <title>SharePoint 2013 Hosted Apps – Do they really work? Part 3</title>
      <link>http://blog.helloitsliam.com/Lists/Posts/ViewPost.aspx?ID=114</link>
      <description><![CDATA[<div><b>Body:</b> <div class="ExternalClass4C033BD287BC48068BD30F7FCB54EC78"><ul><li><a href="/Lists/Posts/Post.aspx?ID=112">SharePoint 2013 Hosted Apps – Do they really work? Part 1</a>
		</li>
<li><a href="/Lists/Posts/Post.aspx?ID=113">SharePoint 2013 Hosted Apps – Do they really work? Part 2</a>
		</li>
<li><a href="/Lists/Posts/Post.aspx?ID=114">SharePoint 2013 Hosted Apps – Do they really work? Part 3</a>
</li>
<li>SharePoint 2013 Hosted Apps – Do they really work? Part 4
</li></ul>
<p>In our last <a href="/Lists/Posts/Post.aspx?ID=113">post</a> we made changes to our SharePoint 2013 Hosted App, to use the REST API to get list items that were selected from a list. When you clicked on the Ribbon button it sent the selected items to the &quot;<strong>default.aspx</strong>&quot; page of the App Web and rendered them accordingly. The code we used for rendering the selected items was not ideal as we just asked the REST service to give me everything and then filter out the ones that are not in the query string. As you can imagine not the most performing code you could write. 
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint21.png" alt="" />
	</p>
<p>To make this better and faster one of the new features of the REST API is to pass filters directly to the call. Firstly let's look at the syntax, we can use. We can test this by using the following URL against our Office 365 site.
</p>
<p><a href="https://demo.sharepoint.com/sites/appdev/_api/web/lists('{List_ID}')/items">https://demo.sharepoint.com/sites/appdev/_api/web/lists('{List_ID}')/items</a>
	</p>
<p>This will let you call the REST API directly and see an RSS feed type result come back. Some basic examples would be to specify the fields that come back. To do this the URL would need to be the following:
</p>
<p><a href="https://demo.sharepoint.com/sites/appdev/_api/web/lists('{B6F5FCC8-5102-4F1B-9F24-D8929162CB51}')/items?select=Title,Body">https://demo.sharepoint.com/sites/appdev/_api/web/lists('%7BB6F5FCC8-5102-4F1B-9F24-D8929162CB51%7D')/items?select=Title,Body</a>
	</p>
<p>When this is ran you should see the following:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint22.png" alt="" />
	</p>
<p>This does not really help us as we would like to see the core XML, I use Fiddler for this, so when you call the URL you are able to inspect the response. You will see a get request similar to this:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint23.png" alt="" />
	</p>
<p>If you select that line and then select the &quot;<strong>Headers</strong>&quot; tab on the right and choose &quot;<strong>XML</strong>&quot; from the bottom you should see the returned XML response.
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint24.png" alt="" />
	</p>
<p>This just helps me see that the right XML is being returned. Using the &quot;<strong>$select</strong>&quot; parameter we can specify as many fields as we wish or simply remove it to show all fields.
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint25.png" alt="" />
	</p>
<p>Now back to the original issue, we want to only retrieve the selected items form the REST API call, not all of them and filter. So we can now use another parameter &quot;<strong>$filter</strong>&quot;. As a simple example let's retrieve one of the items from our &quot;<strong>Announcements</strong>&quot; list.
</p>
<p><a href="https://demo.sharepoint.com/sites/appdev/_api/web/lists('{B6F5FCC8-5102-4F1B-9F24-D8929162CB51}')/items?$filter=ID eq 3&amp;$select=Title,Body">https://demo.sharepoint.com/sites/appdev/_api/web/lists('%7BB6F5FCC8-5102-4F1B-9F24-D8929162CB51%7D')/items?$filter=ID eq 3&amp;$select=Title,Body</a>
	</p>
<p>This URL will render the following:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint26.png" alt="" />
	</p>
<p>And out Fiddler trace shows the following:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint27.png" alt="" />
	</p>
<p>So what if we wanted to filter on multiple values, so in our example let's say we had selected items 3 and 2. Our new filter URL would be the following:
</p>
<p><a href="https://demo.sharepoint.com/sites/appdev/_api/web/lists('{B6F5FCC8-5102-4F1B-9F24-D8929162CB51}')/items?$filter=ID eq 3 or ID eq 2&amp;$select=Title,Body">https://demo.sharepoint.com/sites/appdev/_api/web/lists('%7BB6F5FCC8-5102-4F1B-9F24-D8929162CB51%7D')/items?<span style="background-color:yellow">$filter=ID eq 3 or ID eq 2</span>&amp;$select=Title,Body</a>
	</p>
<p>Our fiddler trace will now return the following:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint28.png" alt="" />
	</p>
<p>So to tie this all together we need to change out code in the &quot;<strong>App.js</strong>&quot; to be the following so it only returns the selected items. Firstly we need to modify the following code:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint29.png" alt="" />
	</p>
<p>This creates a new variable to contain a dynamic query. We then modify the core document ready code to not run and simply show us an alert box saying the &quot;<strong>selectedids</strong>&quot; variable is not populated, in the real world you would change this behavior of course. We then wrap a call to the &quot;<strong>getSelectedItemIDs</strong>&quot; and the rest of the core code to ensure it does not run when nothing has been selected. Now we need to modify the core method &quot;<strong>getSelectedList</strong>&quot; to contain a filtering option.
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint210.png" alt="" />
	</p>
<p>We also need to remove the last code we used in the &quot;<strong>getListSuccess</strong>&quot; method as we are no longer getting all the items and filtering through the loop process.
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint211.png" alt="" />
	</p>
<p>Lastly we need to create the new method &quot;getSelectedItemIDs&quot; which simply splits the query string that contains the selected IDs from the list, loops through them and creates an output that renders like this:
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint212.png" alt="" />
	</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint213.png" alt="" />
	</p>
<p>Now when we run the code, we are able to select values and when we click the ribbon button will render only those, by using the REST API query to just get those items.
</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint214.png" alt="" />
	</p>
<p><img src="/Lists/Photos/041013_1933_SharePoint215.png" alt="" />
	</p>
<p>So to recap we have looked at using the selected items query string, passing it into the REST API call after dynamically create the filter clause then rendering the values out on the page. In the next post we will look at creating the rest of the user interface such as the grid for the specific fields we want to show.
</p></div></div>
<div><b>Category:</b> <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=37&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=37&RootFolder=*">SharePoint 2013</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=7&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=7&RootFolder=*">Development</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=13&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=13&RootFolder=*">How To Code</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=19&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=19&RootFolder=*">Ramblings</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=4&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=4&RootFolder=*">SharePoint</a></div>
<div><b>Published:</b> 4/10/2013 2:35 PM</div>
]]></description>
      <author>liam.cleary</author>
      <category>SharePoint 2013; Development; How To Code; Ramblings; SharePoint</category>
      <pubDate>Wed, 10 Apr 2013 19:33:36 GMT</pubDate>
      <guid isPermaLink="true">http://blog.helloitsliam.com/Lists/Posts/ViewPost.aspx?ID=114</guid>
    </item>
    <item>
      <title>SharePoint 2013 Hosted Apps – Do they really work? Part 2</title>
      <link>http://blog.helloitsliam.com/Lists/Posts/ViewPost.aspx?ID=113</link>
      <description><![CDATA[<div><b>Body:</b> <div class="ExternalClass74C252863C7941AE806FFEC3982BD67C"><ul><li><a href="/Lists/Posts/Post.aspx?ID=112">SharePoint 2013 Hosted Apps – Do they really work? Part 1</a></li>
<li><a href="/Lists/Posts/Post.aspx?ID=113">SharePoint
2013 Hosted Apps – Do they really work? Part 2</a></li>
<li><a href="/Lists/Posts/Post.aspx?ID=114">SharePoint 2013 Hosted Apps – Do they really work? Part 3</a></li>
<li>SharePoint 2013 Hosted Apps – Do they really
work? Part 4
</li></ul>

<p>So in <a href="/Lists/Posts/Post.aspx?ID=112">part 1​</a> we looked at some basic concepts of creating a SharePoint 2013 Hosted App. In this post we will continue with our demonstration app and look to expand it further. We left off with a custom ribbon action that redirects to a page within the App Web and simply just uses the default code from the &quot;<strong>App.js</strong>&quot; to render your display name. As a recap the design we are looking for is to allow a user to select items from a list and then when they click the ribbon be redirected to the App Web and render a grid type view of just the selected items, which we learned from the last post we can get by using query string parameters. So to start we need to open the &quot;<strong>App.js</strong>&quot; file and look at the existing code.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint21.png" alt="" />
	 </p>
<p>This code is very straight forward, as it simple gets a context for SharePoint using the client object model, grabs the current web which in this case is the SharePoint site you clicked the ribbon button from and then gets the &quot;<strong>Current User</strong>&quot; which would be you right now. When the document is loaded which is checked with the following code:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint22.png" alt="" />
	 </p>
<p>A custom function called &quot;<strong>getUserName()</strong>&quot; is called which loads the current user and executes an asynchronous query which on success writes out the name that you see on the page.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint23.png" alt="" />
	 </p>
<p>So let's look at changing this to retrieve data about the SharePoint Site using the REST API that is now available in SharePoint 2013. First off we will need to add the following to the &quot;Default.aspx&quot; page markup.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint24.png" alt="" />
	 </p>
<p>Now we need to remove the current code from &quot;<strong>App.js</strong> and add the following section first.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint25.png" alt="" />
	 </p>
<p>This code declares two variables, then loads them upon document ready from the query strings that are passed in the URL. It then loads a JavaScript files that is used to execute code, and we make a call to a custom method we create called &quot;<strong>getSelectedList</strong>&quot;. The &quot;<strong>getSelectedList</strong>&quot; method for now is not actually getting a list, it will be retrieving the SharePoint Site Title, confusing I know but easier than changing all the code each time.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint26.png" alt="" />
	 </p>
<p>This method makes a call to the &quot;<strong>_api</strong>&quot; URL of SharePoint which an endpoint for the web services / WCF for the client object model components of SharePoint 2013. To read more about this, read the details on MSDN here:
</p>
<p><a href="http://msdn.microsoft.com/en-us/library/jj860569.aspx">http://msdn.microsoft.com/en-us/library/jj860569.aspx</a>
	</p>
<p>In our custom method you will see that we have a success and error call to two methods shown below:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint27.png" alt="" />
	 </p>
<p>These methods simply either render an error or the SharePoint Site Title onto the &quot;<strong>Default.aspx</strong>&quot; page. We also have a helper method for parsing the query strings so we can use them through the code.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint28.png" alt="" />
	 </p>
<p>Now we have all the plumbing done we should be able to build and deploy our solution and it should render as shown below once we click the ribbon button.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint29.png" alt="" />
	 </p>
<p>If we debug the code by adding a break point in the &quot;<strong>App.js</strong>&quot; we can see that we are getting an &quot;<strong>Access Denied</strong>&quot; error.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint210.png" alt="" />
	 </p>
<p><img src="/Lists/Photos/041013_0241_SharePoint211.png" alt="" />
	 </p>
<p>This means that the current account is not allowed to access the root web properties. This is by design and this brings me to another consideration when designing a SharePoint 2013 Hosted App. You need to work out the permission level that you want to assign so when it is deployed the right trust level is set ready for use. To set the permission, double click the &quot;<strong>AppManifest.xml&quot;</strong> file in Visual Studio. Select the &quot;<strong>Permissions</strong>&quot; tab and you will be presented with the following screen:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint212.png" alt="" />
	 </p>
<p>Set this screen to the following:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint213.png" alt="" />
	 </p>
<p>Rebuild the solution deploy using &quot;<strong>F5</strong>&quot; as always from Visual Studio. This time when you deploy you get stopped halfway through and are asked to trust it.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint214.png" alt="" />
	 </p>
<p>Select the &quot;<strong>Trust It</strong>&quot; button and the page will load as shown below:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint215.png" alt="" />
	 </p>
<p>So the key here is that by design the end user who is accessing your application is <strong>NOT</strong> allowed to perform certain functions unless the trust level has been set in the App and accepted during installation. So now we have it working with SharePoint Site data, now let's change the code a little to retrieve a specific list from the site. First off ensure you have an announcements list with some items within the SharePoint Site you are using. 
</p>
<p>Modify the &quot;<strong>Default.aspx</strong>&quot; page to now have the following code, you can remove the last markup we added.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint216.png" alt="" />
	 </p>
<p>We now need to modify the custom function we wrote to now use the following:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint217.png" alt="" />
	 </p>
<p>The success and failure method also need to be changed slightly too.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint218.png" alt="" />
	 </p>
<p>As before now build and deploy using Visual Studio so we can debug if needed. Accept the &quot;<strong>Trust</strong>&quot; and it should render as shown below:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint219.png" alt="" />
	 </p>
<p>Now that we are able to render the values let's make some changes to the code so it will work for any list that we decide to click the ribbon button from. To do this lets first look at the URL:
</p>
<p><a href="https://demo-5551df50f28634.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https://demo.sharepoint.com/sites/appdev&amp;SPLanguage=en-US&amp;SPClientTag=0&amp;SPProductNumber=15.0.4454.1034&amp;SPAppWebUrl=https://demo-5551df50f28634.sharepoint.com/sites/appdev/DemoApp&amp;SelectedList={B6F5FCC8-5102-4F1B-9F24-D8929162CB51}&amp;SelectedItems=3,2">https://demo-5551df50f28634.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https%3A%2F%2Fdemo%2Esharepoint%2Ecom%2Fsites%2Fappdev&amp;SPLanguage=en%2DUS&amp;SPClientTag=0&amp;SPProductNumber=15%2E0%2E4454%2E1034&amp;SPAppWebUrl=https%3A%2F%2Fdemo%2D5551df50f28634%2Esharepoint%2Ecom%2Fsites%2Fappdev%2FDemoApp&amp;SelectedList={B6F5FCC8-5102-4F1B-9F24-D8929162CB51}&amp;SelectedItems=3,2</a>
	</p>
<p>If we look in the link above we have the query string from the last post already in there, which is &quot;<strong>SelectedList={B6F5FCC8-5102-4F1B-9F24-D8929162CB51}</strong>&quot;, this means we already have the list ID so if we modify the code a little we should be able to use this dynamic value, instead of hard coding &quot;<strong>Announcements</strong>&quot;. To achieve this firstly add the following to &quot;<strong>App.js</strong>&quot;.
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint220.png" alt="" />
	 </p>
<p>This will get us the list ID loaded into a variable we can use throughout the code. Now we need to modify the &quot;<strong>getSelectedList</strong>&quot; method code to be the following:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint221.png" alt="" />
	 </p>
<p>Once complied and deployed you are then able to click any list and it should render details as shown below.
</p>
<p><strong>Announcement List
</strong></p>
<p><img src="/Lists/Photos/041013_0241_SharePoint222.png" alt="" />
	 </p>
<p><strong>Contacts List
</strong></p>
<p><img src="/Lists/Photos/041013_0241_SharePoint223.png" alt="" />
	 </p>
<p>So now we have the code working for any list now we need to look at restricting the list of items that is renders to the selected items that are passed in the URL. We need to change the code in the &quot;<strong>App.js</strong>&quot;. 
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint224.png" alt="" />
	 </p>
<p>Next we need to change the rendering code to be the following:
</p>
<p><img src="/Lists/Photos/041013_0241_SharePoint225.png" alt="" />
	 </p>
<p>Now build and deploy from Visual Studio so you can debug and you should now be able to select items within the list and when the page renders it will only display the selected items. Of course there are better way of doing this but we will save that for another day.
</p>
<p>In the next post we will look at the options available for rendering more than just &quot;<strong>Title</strong>&quot; and &quot;<strong>Body</strong>&quot; fields and actually create the grid view we need.
</p></div></div>
<div><b>Category:</b> <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=37&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=37&RootFolder=*">SharePoint 2013</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=7&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=7&RootFolder=*">Development</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=13&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=13&RootFolder=*">How To Code</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=4&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=4&RootFolder=*">SharePoint</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=19&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=19&RootFolder=*">Ramblings</a></div>
<div><b>Published:</b> 4/9/2013 9:43 PM</div>
]]></description>
      <author>liam.cleary</author>
      <category>SharePoint 2013; Development; How To Code; SharePoint; Ramblings</category>
      <pubDate>Wed, 10 Apr 2013 02:42:34 GMT</pubDate>
      <guid isPermaLink="true">http://blog.helloitsliam.com/Lists/Posts/ViewPost.aspx?ID=113</guid>
    </item>
    <item>
      <title>SharePoint 2013 Hosted Apps – Do they really work? Part 1</title>
      <link>http://blog.helloitsliam.com/Lists/Posts/ViewPost.aspx?ID=112</link>
      <description><![CDATA[<div><b>Body:</b> <div class="ExternalClassF9B1FF7C5E6A49C08A7F4B8F9D7F9F38"><ul><li><span style="font-family:symbol"></span><a href="/Lists/Posts/Post.aspx?ID=112">SharePoint 2013 Hosted Apps – Do they really work? Part 1</a></li>

<li><span style="font-family:symbol"><span><span style="font:7pt &quot;times new roman&quot;"></span></span></span><a href="/Lists/Posts/Post.aspx?ID=113">SharePoint
2013 Hosted Apps – Do they really work? Part 2</a></li>
<li><span style="font-family:symbol"><span><span style="font:7pt &quot;times new roman&quot;"></span></span></span><a href="/Lists/Posts/Post.aspx?ID=114">SharePoint 2013 Hosted Apps – Do they really work? Part 3</a></li>
<li><span style="font-family:symbol"><span><span style="font:7pt &quot;times new roman&quot;"></span></span></span>SharePoint 2013 Hosted Apps – Do they really
work? Part 4</li></ul>

<p>Recently I have spent some time working through building and converting demonstration code across to SharePoint 2013 Apps and have a fun time learning what can be done and really what can't be done. This post is based my practical experience so far of trying to use &quot;<strong>SharePoint Hosted Apps</strong>&quot; only. The reason for this was to make an App that would work on-premise and on Office 365 with no dependency on managed code but to use pure JavaScript.
</p>
<p>So to create a new SharePoint 2013 Hosted App you need to ensure that when you create the project in Visual Studio you select the correct option.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint21.png" alt="" />
	</p>
<p>Once the project is created you should get a structure similar to this:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint22.png" alt="" />
	</p>
<p>The basic construct is the following:
</p>
<ol><li>Feature Folder – Normal SharePoint Feature dialog you have used in the previous tooling
</li>
<li>Content Folder – Any specific content that will reside in the App Web, by default the App.CSS file
</li>
<li>Images Folder – Images that will reside in the App Web
</li>
<li>Pages Folder – The core pages that will reside in the App Web (Core User Experience)
</li>
<li>Scripts Folder – Contains all JavaScript files, such as jQuery and the core App.js, once again all hosted in the App Web
</li>
<li>AppManifest File – Base configuration and permission sets for the App
</li></ol>
<p>If we deploy this solution as is, it will render values that are called from the App.js file. This will display your current display name.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint23.png" alt="" />
	</p>
<p>This page is loaded from the App Web, this is the separate web site that gets stood up as part of the new App Model. A SharePoint 2013 Hosted App when deployed does this automatically and crea6es a URL similar to this:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint24.png" alt="" />
	</p>
<p>So the first things to note here is that the code and other assets do not live inside SharePoint, so that changes the overall design considerably. So the user experience becomes slightly more complicated than before. Whereas we would write code either full trust or even sandboxed code it would be deployed directly into SharePoint, so simple things such as deploying files like images, CSS or JavaScript to the style library was still supported, now it is not. Sean McDonough has a great blog post about imaging rendering and SharePoint 2013 Apps in General, I would suggest a read:
</p>
<p><a href="http://sharepointinterface.com/2013/01/22/custom-ribbon-button-image-limitations-with-sharepoint-2013-apps/">http://sharepointinterface.com/2013/01/22/custom-ribbon-button-image-limitations-with-sharepoint-2013-apps/</a>
	</p>
<p>So let's think about an example app we could build. For this demonstration I would like an end user to access a list, see the list items, press a ribbon button, and then popup a dialog over the top listing out the selected items only and then allow the end user to perform some action. I can hear you thinking this is going to be easy. Write a full trust solution that does the following:
</p>
<ol><li>Deploys JavaScript, CSS and Images
</li>
<li>Adds a Ribbon Button, maybe as a custom &quot;<strong>Additional Page Head</strong>&quot; control so it shows up on all Ribbon Bars
</li>
<li>Uses C# to get the currently viewed list
</li>
<li>Uses JavaScript to get the selected items
</li>
<li>Opens the Dialog
</li>
<li>Loads a custom page, maybe &quot;<strong>_layouts</strong>&quot; page
</li>
<li>Custom Page uses C# to get the currently selected list, renders only the selected items based on what is passed to it
</li></ol>
<p>Of course there are many ways of doing this same thing whether using Full Trust C# or Sandboxed Client Object Model code. So how do we do this for a SharePoint 2013 Hosted App. First off let's look at adding a ribbon button. In the Visual Studio right click he project and select &quot;<strong>Add New Item</strong>&quot;. From the list select the &quot;<strong>Ribbon Custom Action</strong>&quot;.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint25.png" alt="" />
	</p>
<p>Once selected you are asked to define the type of Ribbon Action. The first thing is where you wish this custom action to reside. The Host Web is SharePoint, the App Web is the funny website that got created in my Office 365 Tenant when I deployed it. As we need this ribbon button to be in the current SharePoint, we will select the &quot;<strong>Host Web&quot; </strong>option. We also have the ability to scope the action to one of the following:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint26.png" alt="" />
	</p>
<p>The interface does not allow for scoping actions to anything other than List Templates and List Instances. Selecting List Template will populate the second dropdown with the available list templates in the SharePoint site that is connected to Visual Studio. If you select List Instance it will populate the dropdown with available lists that are deployed and active in the SharePoint site. For this example we are going to choose &quot;None&quot; as I would like to associate this action to more than one list or template.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint27.png" alt="" />
	</p>
<p>The tooling then let's you select the control location from a predefined list:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint28.png" alt="" />
	</p>
<p>This list is great but once again does not list every location you would want to use. You can overtype this with your own values if needed. For this demonstration we will use &quot;<strong>Ribbon.List.Actions</strong>&quot;, with the control navigation set to the default page.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint29.png" alt="" />
	</p>
<p>Visual Studio will then create the custom action object in the project and the &quot;<strong>elements.xml</strong>&quot; file is loaded and will look similar to this:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint210.png" alt="" />
	</p>
<p>The code looks fairly straight forward and what you would be used to seeing, however notice that the &quot;<strong>CommandUIHandler</strong>&quot; is a redirect to the following URL:
</p>
<p><strong>~appWebUrl/Pages/Default.aspx?{StandardTokens}
</strong></p>
<p>You will notice it is using a token for the URL, the &quot;<strong>~appWebUrl</strong>&quot; is a unique one that SharePoint 2013 understands and will replace at the build and deployment time into the full URL of the App Web, so it will end up being something like this:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint211.png" alt="" />
	</p>
<p>You will also see an appended query string of &quot;<strong>StandardTokens</strong>&quot;, this is one of the replacement tokens that are available. This specific one combines five other tokens. &quot;<strong>SPHostUrl</strong>&quot;, &quot;<strong>SPAppWebUrl</strong>&quot;, &quot;<strong>SPLanguage</strong>&quot;, &quot;<strong>SPClientTag</strong>&quot; and &quot;<strong>SPProductNumber</strong>&quot;. Sahil Malik has a list of all the tokens that are available in SharePoint 2013 Apps and when they can be used.
</p>
<p><a href="http://blah.winsmarts.com/2013-2-SharePoint_2013_apps_replacement_tokens.aspx">http://blah.winsmarts.com/2013-2-SharePoint_2013_apps_replacement_tokens.aspx</a>
	</p>
<p>Let's say we wanted to change this mechanism to use a simple piece of JavaScript. SO something simple like this: &quot;<strong>javascript:alert('Hello World');</strong>&quot;, we would change the XML to be the following:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint212.png" alt="" />
	</p>
<p>Now if we build the application is Visual Studio all is well. Now if we try to deploy it something strange happens.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint213.png" alt="" />
	</p>
<p>It errors with the deployment saying there are errors in the package. This is because you <strong>CANNOT</strong> run inline JavaScript inside ribbon actions at all. This is a big difference to the full trust and sandboxed design we currently have in SharePoint 2010. So from a user experience for something like this we would need to explain to the end user that every time they click the ribbon it will take them out of the SharePoint site to perform the task and then we would need to handle through code the redirect back or the end user would be stuck in the app not SharePoint. By default however you will notice that the App Web is styled with a similar chrome to SharePoint itself, along with a link to get back to the site you came from, this will help in the user experience.
</p>
<p>So back to performing a redirect, this means we need to write the code in the App Web for getting list items etc. as per our design for this demonstration app. If we change the code back and build and deploy we should be back to the site now. To test the ribbon we can access a list and see in the &quot;<strong>Actions</strong>&quot; section our new button.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint214.png" alt="" />
	</p>
<p>If you click this button it will redirect you to the App Web and show the default page. If we look at the URL we can see the token values:
</p>
<p><a href="https://demo-5551df50f2862e.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https://demo.sharepoint.com/sites/appdev&amp;SPLanguage=en-US&amp;SPClientTag=0&amp;SPProductNumber=15.0.4454.1032&amp;SPAppWebUrl=https://demo-5551df50f2862e.sharepoint.com/sites/appdev/DemoApp">https://demo-5551df50f2862e.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https%3A%2F%2Fdemo%2Esharepoint%2Ecom%2Fsites%2Fappdev&amp;SPLanguage=en%2DUS&amp;SPClientTag=0&amp;SPProductNumber=15%2E0%2E4454%2E1032&amp;SPAppWebUrl=https%3A%2F%2Fdemo%2D5551df50f2862e%2Esharepoint%2Ecom%2Fsites%2Fappdev%2FDemoApp</a>
	</p>
<p>This is great as it already passes a lot of information that we would need to us in the App Web, such as the actual site we are in. We can change our Visual Studio solution to also send us further details, such as the ID's of the selected items, the list ID and name. To do this we need to make changes to the &quot;<strong>CommandAction</strong>&quot; link. Modify the link to be the following:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint215.png" alt="" />
	</p>
<p>Now build and deploy the solution and test the link this time. This time access the list and select a few items as shown below and click the ribbon link and the URL should now be similar to this:
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint216.png" alt="" />
	</p>
<p><a href="https://demo-5551df50f28632.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https://demo.sharepoint.com/sites/appdev&amp;SPLanguage=en-US&amp;SPClientTag=0&amp;SPProductNumber=15.0.4454.1032&amp;SPAppWebUrl=https://demo-5551df50f28632.sharepoint.com/sites/appdev/DemoApp&amp;SelectedList={B6F5FCC8-5102-4F1B-9F24-D8929162CB51}&amp;SelectedItems=3,2">https://demo-5551df50f28632.sharepoint.com/sites/appdev/DemoApp/Pages/Default.aspx?SPHostUrl=https%3A%2F%2Fdemo%2Esharepoint%2Ecom%2Fsites%2Fappdev&amp;SPLanguage=en%2DUS&amp;SPClientTag=0&amp;SPProductNumber=15%2E0%2E4454%2E1032&amp;SPAppWebUrl=https%3A%2F%2Fdemo%2D5551df50f28632%2Esharepoint%2Ecom%2Fsites%2Fappdev%2FDemoApp&amp;SelectedList={B6F5FCC8-5102-4F1B-9F24-D8929162CB51}&amp;SelectedItems=3,2</a>
	</p>
<p>This time you will notice that we get the list ID and the selected ID's of the values we selected in the list, so now we just have to wire up the new page in the App Web to display these items in a list view type grid. 
</p>
<p>This design now means that we need to allow the end user to perform the required tasks such as selecting items in SharePoint, send that to the App Web and then re-connect to the SharePoint site and list or library using the client object model or the REST API features. This logic will be added to the &quot;<strong>App.js</strong>&quot; file which is referenced in the &quot;<strong>default.aspx</strong>&quot; page.
</p>
<p><img src="/Lists/Photos/040813_1600_SharePoint217.png" alt="" />
	</p>
<p>The &quot;<strong>App.js</strong>&quot; file allows us to add any JavaScript or JSOM code to connect or interrogate SharePoint. Be aware that this is a subset of the core API that is available in SharePoint. In the next post we will look at writing JavaScript code in the &quot;App.js&quot; along with the pro's and con's to this design.</p></div></div>
<div><b>Category:</b> <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=37&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=37&RootFolder=*">SharePoint 2013</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=7&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=7&RootFolder=*">Development</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=4&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=4&RootFolder=*">SharePoint</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=19&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=19&RootFolder=*">Ramblings</a>; <a onclick="OpenPopUpPage('http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=13&RootFolder=*', RefreshPage); return false;" href="http://blog.helloitsliam.com/_layouts/listform.aspx?PageType=4&ListId={6C530EF0-95A1-46C3-912A-D18ED1B094AC}&ID=13&RootFolder=*">How To Code</a></div>
<div><b>Published:</b> 4/8/2013 11:02 AM</div>
]]></description>
      <author>liam.cleary</author>
      <category>SharePoint 2013; Development; SharePoint; Ramblings; How To Code</category>
      <pubDate>Mon, 08 Apr 2013 16:01:08 GMT</pubDate>
      <guid isPermaLink="true">http://blog.helloitsliam.com/Lists/Posts/ViewPost.aspx?ID=112</guid>
    </item>
  </channel>
</rss>