tag:blogger.com,1999:blog-18048652428500181282024-03-14T00:38:08.216+07:00Sohel's BlogAnonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.comBlogger175125tag:blogger.com,1999:blog-1804865242850018128.post-11672655688819863312016-11-25T12:23:00.000+07:002016-11-25T12:29:14.803+07:00JSON based Site Template – Frist Release<p>I’ve published the SharePoint App in <a href="https://github.com/ranaictiu/SP-JSON-Provisioning-Engine" target="_blank">GitHub</a> recently. The app needs to be installed at site collection level (root web). The app uses the following two types of templates:</p> <ul> <li>Site Template – used to create new site. </li> <li>Feature Template – used in existing sites to apply new features. </li> </ul> <p>When the app will be launched, user will be provided a tree view of the site collection and option to create a new site under the selected site or apply a feature template to existing site.</p> <p><a href="https://lh3.googleusercontent.com/-2G1Nf2mXUWA/WDfMGCMvfbI/AAAAAAAACbw/32YEgpg0vns/s1600-h/image3.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-yra4CjtvZL0/WDfMG94V5YI/AAAAAAAACb0/AvPqCTZzH14/image_thumb1.png?imgmax=800" width="458" height="296" /></a></p> <p>Image 1: Home Page</p> <p> </p> <h4>Site Template</h4> <p>When user will select ‘create sub-site’ from home page teh following form will be provide to user:</p> <p><a href="https://lh3.googleusercontent.com/-iyUNr87xzkI/WDfMHUW2UAI/AAAAAAAACb4/_LemxtDtiDI/s1600-h/image8.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-6FLn8JnFEfQ/WDfMIKsqSII/AAAAAAAACb8/KUxg6Jm41uI/image_thumb4.png?imgmax=800" width="679" height="772" /></a></p> <p>Image 2: Create Sub-site page</p> <p> </p> <p>Once user provides subsite details and click ‘create site’ the following progress screen will be showing:</p> <p><a href="https://lh3.googleusercontent.com/-U6cZOu4eJqU/WDfMIv_nQtI/AAAAAAAACcA/EcP7eV9LsTk/s1600-h/image12.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-50L2hIy8ivI/WDfMJOCGynI/AAAAAAAACcE/8mtLKPvfs5I/image_thumb6.png?imgmax=800" width="787" height="623" /></a></p> <p>Image 3: Creating site progress</p> <p> </p> <h4>Feature Template</h4> <p>The app comes with few feature templates built-in. As shown in the following image, all available templates will be shown in the screen:</p> <p><a href="https://lh3.googleusercontent.com/-GtGHTJZJt5w/WDfMJvtcnKI/AAAAAAAACcI/aPvD1j5YGpE/s1600-h/image16.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-lcF6pPmJunw/WDfMKWsUwkI/AAAAAAAACcM/Ckdxf37W6Ww/image_thumb8.png?imgmax=800" width="1036" height="399" /></a></p> <p>Image 4: Feature Template Page</p> <p> </p> <p> </p> <h4>Conclusion</h4> <p>Feel free to use the source <a href="https://github.com/ranaictiu/SP-JSON-Provisioning-Engine" target="_blank">from GitHub</a> and let me you know if you  have any suggestions or issues.</p>Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-5143391955993278772016-09-07T14:09:00.001+07:002016-09-07T14:09:55.765+07:00JSON based Site Template – Introduction<p>PnP Provisioning engine is really powerful to create and provision site templates. However PnP uses CSOM – which means to use PnP provision engine, we need to develop either desktop based application (console, wpf) or Provider hosted app. Would be nice to use PnP like templating to create site using SharePoint hosted Add-in which only supports JSOM.</p> <p>Recently I worked with a client who needed to create sites based on site templates but didn’t want to use Provider hosted app nor any desktop application to provision new site based on site template. This is what I did for the client (more details will be provided in later blogs):</p> <ol> <li>Provisioned a site collection based on PnP Provisioning Engine. <ul> <li>Common Site Columns, Content Types are provisioned at site collection level. </li> <li>Custom js (jquery, knockout) uploaded at site collection level and referenced in master page through custom action </li> <li>Custom css uploaded at site collection level and used in alternate css property. </li> </ul> </li> <li>The actual site template is created in PnP provision template but never used. Rather the template is converted to json using ‘JsonPnPFormatter’ and saved as json file.  More details provided later in this post. </li> <li>A SharePoint hosted Add-in is developed to create site based on site template and installed at site collection level. The add-in creates a new site and then reads the json file created from PnP template and provision artefacts as defined in json template. The Add-In does the followings: <ul> <li>Create Site, Site Groups </li> <li>Create lookup fields and create content types </li> <li>create lists </li> <li>setup navigation </li> <li>and many more </li> </ul> </li> </ol> <p>Since provisioning site collection/site based on PnP template is not part of this post,I’ll skip step 2.  I’ll explain step 2 – ‘convert PnP template to Json’ in this post. In later posts I’ll explain step 3 – ‘provision site based on json site template’.</p> <h4>Convert PnP template to JSON</h4> <p>To convert PnP template to json, you can use the following code snippet. </p> <div id="codeSnippetWrapper"> <pre id="codeSnippet" class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> SaveTemplateAsJson(<span class="kwrd">string</span> templateFilePath, <span class="kwrd">string</span> templateName, <span class="kwrd">string</span> outputFilePath)<br />{<br /> var templateProvider = <span class="kwrd">new</span> XMLFileSystemTemplateProvider(Path.GetDirectoryName(templateFilePath), <span class="str">""</span>);<br /> var template = templateProvider.GetTemplate(Path.GetFileName(XmlPath));<br /> templateProvider.SaveAs(template, outputFilePath, <span class="kwrd">new</span> JsonPnPFormatter());<br />}</pre>
<br /></div>
<p>You can call the above method as </p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" class="csharpcode">SaveTemplateAsJson(<span class="str">@"c:\templates\PnPTempalte.xml"</span>, <span class="str">"TemplateName"</span>, <span class="str">@"c:\templates\PnPTempalte.json"</span>);</pre>
<br /></div>
<p>To get a visual representation of Json file you can use online tools like <a title="http://jsoneditoronline.org/" href="http://jsoneditoronline.org/">http://jsoneditoronline.org/</a> or <a title="http://jsonviewer.stack.hu/" href="http://jsonviewer.stack.hu/">http://jsonviewer.stack.hu/</a></p>
<p> </p>
<p>Now we are ready to use this JSON file in SharePoint Add-in to create site based on this template. If you need to convert multiple PnP templates to Json you can modify the SaveTemplateAsJson to do so.</p>
<p>I’ll explain how to use this json template to create SharePoint Add-in in my future posts.</p>Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-81501198658335618682015-02-19T10:53:00.001+07:002015-02-19T10:54:40.256+07:00SharePoint 2013 Workflow: Code Activity Vs Service Call<p>SharePoint 2013 has introduced a new workflow model. The workflow model is mostly declarative (XML based). However, you might need to write custom code to implement complex business logic which the workflow itself doesn’t support. You have two options to implement code in this new workflow model:</p> <ul> <li>Code activity </li> <li>WCF Service </li> </ul> <p>Now having these two options to implement, you need to know the pros and cons of both.</p> <p>Let me compare these two options considering full-trust solution.</p> <table cellspacing="0" cellpadding="2" width="1292" border="1"><tbody> <tr> <td valign="top" width="174"><strong><font size="4">Options/Matrix</font></strong></td> <td valign="top" width="411"><strong><font size="4">Code Activity</font></strong></td> <td valign="top" width="259"><strong><font size="4">WCF Service</font></strong></td> <td valign="top" width="446"><strong><font size="4">Comments</font></strong></td> </tr> <tr> <td valign="top" width="174"><strong>Object Model</strong></td> <td valign="top" width="411">You can use Client object model or server object model but better to user Client Object model as this gives you the flexibility to move the workflow manager (along with custom code activity) to non-SharePoint server for scalability. <br /></td> <td valign="top" width="259">You can use Server Object Model as the service will be hosted in SharePoint</td> <td valign="top" width="446">You should not use Server object model in code activity as the workflow services can be moved to non-SharePoint server for scalability</td> </tr> <tr> <td valign="top" width="174"><strong>Development</strong></td> <td valign="top" width="411"> <ul> <li>Since you should use client object model, you need to be familiar with client object model. </li> <li>The development involved few manual steps like creating xml file etc. </li> </ul> </td> <td valign="top" width="259">Easy to develop – just like regular Visual Studio solution (SharePoint template)</td> <td valign="top" width="446"> </td> </tr> <tr> <td valign="top" width="174"><strong>Deployment</strong></td> <td valign="top" width="411">Deployment requires copying files in different places, no out-of-box commands to deploy Code Activity</td> <td valign="top" width="259">Deployment is easy if you are familiar with WSP deployment</td> <td valign="top" width="446">If you don’t have remote access to the server (SharePoint admin will deploy using scripts for you), then code activity deployment might be a bit troublesome</td> </tr> <tr> <td valign="top" width="174"><strong>Scalability</strong></td> <td valign="top" width="411">If you use Server Object model, you can’t move workflow manager to it’s own non-SharePoint Server. However if you use client object model, you can move workflow manager to it’s own non-SharePoint server.</td> <td valign="top" width="259">Since it’s service, you can scale it anyway, like workflow manager and SharePoint server can be hosted in on-premise, cloud or hybrid.</td> <td valign="top" width="446"> </td> </tr> <tr> <td valign="top" width="174"><strong>Reusability</strong></td> <td valign="top" width="411">If you want to reuse the logic in workflow code activity, you might find it difficult</td> <td valign="top" width="259">Since your logic is hosted as WCF service, you can reuse the logic in other modules</td> <td valign="top" width="446"> </td> </tr> <tr> <td valign="top" width="174"><strong>Execution</strong></td> <td valign="top" width="411">I think code activity will run faster as it’ll be executed inside workflow manager.</td> <td valign="top" width="259">Service call will a bit slower than code activity, I believe</td> <td valign="top" width="446">This is based on assumption… </td> </tr> </tbody></table> <p> </p> <p>Workflow Manager in SharePoint 2013 is designed in a way that it can run independently in non-SharePoint server. Basically Workflow Manager and SharePoint communicate over REST endpoints. So if you use server object model in code activity you are breaking the overall architecture and bring the server side dependency. So in code activity it’s recommended to use either client object model or REST.</p> <p> </p> <p>For calling WCF service, you can use built-in activity HttpGet/HttpPost.</p> <p> </p> <h4>Conclusion</h4> <p>I personally prefer service approach. I can use server object model, I can reuse the service in other modules and it’s easy to deploy/manage. However, if your custom code activity is doing something non-SharePoint related, like getting data from Line of Business (LOB) system, then maybe it’s better to code activity. It’s because it’s doesn’t make sense to deploy the logic (accessing data in LOB systems) in SharePoint.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-8981711004541991792014-11-30T19:40:00.001+07:002014-11-30T19:40:43.791+07:00SharePoint 2013: Client Side People Picker<h4>Introduction</h4> <p>SharePoint 2013 introduced client side people picker which can also be used from SharePoint apps. As like other SharePoint controls, the new people picker control is not well documented. I’ve reversed engineered the client side people picker control and tried to put some light in this dark area.</p> <p> </p> <h4>Functions</h4> <p>In the code snippet below, you can use user login id, email address as the key resolve the user in people picker.</p> <h5><u>Add Unresolved User</u></h5> <p>If you have user login Id or email address you can use them as key to add the user in people picker as shown below. By passing the ‘true’ as the last parameter in <em>AddUnresolvedUser</em> means, people picker will use the key to query the user details from server.</p> <pre class="csharpcode"><span class="kwrd">var</span> peoplePicker = <span class="kwrd">this</span>.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan;
<span class="kwrd">var</span> usrObj = { <span class="str">'Key'</span>: loginIdOrEmail };
peoplePicker.AddUnresolvedUser(usrObj,<span class="kwrd">true</span>); </pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style><style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<h5><u>Add users or show auto suggest</u></h5>
<p>If you would like to show auto suggest box using javascript, you can use the following code snippet. if you pass <em>true</em> in the second parameter for <em>AddUserKeys</em> function, people picker will show the auto-suggest box, otherwise it’ll try to resolve the user. In case of passing true, you can pass any search-text and people picker will show the autosuggest based on the input search text.</p>
<pre class="csharpcode"><span class="kwrd">var</span> peoplePicker = <span class="kwrd">this</span>.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan;
peoplePicker.AddUserKeys(loginIdOrEmailOrSearchText, <span class="kwrd">false</span>); <span class="rem">//true shows the auto-suggest box, false resolve the user</span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<p><u>Show Error Message</u></p>
<p>You can show an error message using code snippet as shown below:</p>
<pre class="csharpcode">SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.ShowErrorMessage(<span class="str">'Error message...'</span>)</pre>
<p>As as result you will the following error message:</p>
<p><a href="http://lh6.ggpht.com/-ClCag0fE_3Q/VHsQRruM76I/AAAAAAAABiE/zX7H95W8J1s/s1600-h/image2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-SU7tz8y96vA/VHsQSP-4oWI/AAAAAAAABiM/IcUetPqumMw/image_thumb.png?imgmax=800" width="244" height="55" /></a></p>
<h5> </h5>
<h5><u>IsEmpty</u></h5>
<p>You can check if People picker is empty using the following code snippet. For your information, if there’s any text in the people picker textbox IsEmpty will return false. Basically it’ll check if there’s any resolved or unresolved text in the people picker editor textbox.</p>
<pre class="csharpcode">SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.IsEmpty()</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<p><u>HasResovledUsers</u></p>
<p>You can check if there’s any resolved user by using the following code snippet. If there’s at least one resolved user in the editor, it’ll return true (even if you have resolved or unresolved user, it’ll return true). The different between IsEmpty and HasResolvedUsers is that IsEmtpy will check if there’s any text in the people picker text box. Whereas HasResolvedUsers check if there’s any resolved users in the editor.</p>
<pre class="csharpcode">SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.HasResolvedUsers()</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<h5><u>Get Current Editor Value</u></h5>
<p>If you can get the editor’s current unresolved value by using the following code snippet:</p>
<pre class="csharpcode">SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.GetCurrentEditorValue()</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>The code snippet will not return any resolved value in the editor rather unresolved value
<p> </p>
<h5><u>Enable/disable</u></h5>
<p>You can use the following code snippet to enable or disable the people picker editor. However setting in disable state, prevent adding any new users in the editor but still user can remove existing resolved users by clicking cross (x) sign next to resolved user.</p>
<pre class="csharpcode">SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.SetEnabledState(<span class="kwrd">false</span>)</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>I think the easiest way to disable completely is to hide the delete (cross X) icon. You can do so using the following script:</p>
<pre class="csharpcode">$(<span class="str">'.sp-peoplepicker-delImage'</span>).hide()</pre>
<p> </p>
<h5><u>Remove Resolved Users</u></h5>
<p>There’s no direct support for removing resolved users using the people picker API. I’ve put the following snippet below which I think should work and removes a user by using selected user’s key.</p>
<pre class="csharpcode"><span class="kwrd">var</span> peoplePickerId = <span class="str">'peoplePickerDiv'</span>;
<span class="kwrd">var</span> peoplePicker = <span class="kwrd">this</span>.SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerId + <span class="str">'_TopSpan'</span>];
<span class="rem">//get selected users and select the second user (index 1) to remove</span>
<span class="kwrd">var</span> selectedUsers = peoplePicker.GetAllUserInfo();
<span class="kwrd">var</span> userToRemoveKey = selectedUsers[1].Key;
<span class="kwrd">var</span> resovledListElmId = peoplePicker.ResolvedListElementId;
<span class="kwrd">var</span> elementToRemove = <span class="str">''</span>;
$(<span class="str">'#'</span> + resovledListElmId).children().each(<span class="kwrd">function</span>(index, element) {
<span class="kwrd">if</span> (element.id.startsWith(peoplePickerId + <span class="str">'_TopSpan_'</span> + userToRemoveKey + <span class="str">'_ProcessedUser'</span>)) {
elementToRemove = element;
<span class="kwrd">return</span> <span class="kwrd">false</span>;
}
});
peoplePicker.DeleteProcessedUser(elementToRemove);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Simply, for all resolved users people picker creates span elements with id in the form ‘{peoplepickerid}_TopSpan_{userKey}_ProcessedUser_{index}’. So if we know the user key we want to remove, we can find the corresponding resolved user’s span element. Then finally people picker’s ‘DeleteProcessedUser’ method is used to remove the selected user.</p>
<p> </p>
<h4>Events</h4>
<p>There’s few events available in the people picker control as described below. All of these events will get two parameters – first one is the people picker id and second parameter is an array of selected users.</p>
<h5><u>On Control Value Changed</u></h5>
<p>This event will be fired if anything changes, like if user type text, user select a user from auto-fill list or user removes selected user. You can easily hook into the event as shown below:</p>
<pre class="csharpcode"> <span class="kwrd">this</span>.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.OnValueChangedClientScript=<span class="kwrd">function</span> (peoplePickerId, selectedUsersInfo) {
console.log(<span class="str">'inside OnValueChangedClientScript'</span>);
};</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<h5> </h5>
<h5><u>On Control Resolved Users Changed</u></h5>
<p>This event will be fired as soon as an user is resolved ( i.e., a resolved user is selected). You can hook into the event as shown below:</p>
<pre class="csharpcode"> <span class="kwrd">this</span>.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.OnUserResolvedClientScript = <span class="kwrd">function</span> (peoplePickerId, selectedUsersInfo) {
console.log(<span class="str">'inside OnUserResolvedClientScript'</span>);
};</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<p><u>On Control Validate</u></p>
<p>The people picker control validate it’s values – sometimes when values are changed or you can fire the event by yourself by calling the method ‘Validate’. You can hook into the event as shown below:</p>
<pre class="csharpcode"> <span class="kwrd">this</span>.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan.OnControlValidateClientScript = <span class="kwrd">function</span> (peoplePickerId, selectedUsersInfo) {
console.log(<span class="str">'inside OnControlValidateClientScript'</span>);
};</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p> </p>
<h4>Conclusion</h4>
<p>I’ve tried to explain the API but you all are welcome to provide any feedback or suggestions or enhancements in this unofficial documentation.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com16tag:blogger.com,1999:blog-1804865242850018128.post-1485125738701988582014-09-29T17:00:00.001+07:002014-09-29T17:05:22.778+07:00SharePoint 2013: Branding with Theme<p>Theme is a nice and quick way of applying some new styles to SharePoint site. Using theme you can apply some customisation in branding: font, color, background image etc. In this post I’ll explain SharePoint 2013 Theme and you can download a <a href="http://1drv.ms/1DQu1pO" target="_blank">sample SharePoint 2013 Visual Studio solution</a> from here.</p> <p>There’s some out-of-the-box theme preinstalled in SharePoint. However you can install your own custom theme in SharePoint site. </p> <p> </p> <h4>Theme - Concept</h4> <p>A theme is combination of the following items:</p> <ul> <li>Color palette (a file with ‘.spcolor’ extension) </li> <li>A font scheme (a file with ‘.spfont’ extension) </li> <li>Background Image (if you would like to apply/change background image for this theme) </li> <li>Master page, used for theme preview mainly </li> </ul> <p>You can browse the URL <a title="http://sohel.dev.local/_catalogs/design/AllItems.aspx" href="http://{SiteCollection}/_catalogs/design/AllItems.aspx">http://{SiteCollection}/_catalogs/design/AllItems.aspx</a> to view all theme list items.</p> <p>Let me explain the theme components:</p> <h5><u>Color Palette</u></h5> <p>If you are not already familier with color palette – simply it’s a set of consistent colors to be used for designing/painting. You can find a lots of free site to choose color palette. Some free color platte sites are listed below. If you are designing your SharePoint site then these color palette sites can be really helpful:</p> <ul> <ul> <li><a title="http://www.colourlovers.com/palettes" href="http://www.colourlovers.com/palettes">http://www.colourlovers.com/palettes</a> </li> <li><a title="http://colorschemedesigner.com/csd-3.5/" href="http://colorschemedesigner.com/csd-3.5/">http://colorschemedesigner.com/csd-3.5/</a> </li> <li><a title="https://kuler.adobe.com/create/color-wheel/" href="https://kuler.adobe.com/create/color-wheel/">https://kuler.adobe.com/create/color-wheel/</a> </li> </ul> </ul> <p>Once you select your color palette, you can use a tool called ‘<a href="http://www.microsoft.com/en-au/download/details.aspx?id=38182" target="_blank">SharePoint Color Palette Tool</a>’ to apply your color palette to design the theme. The following image shows the tool in action:</p> <p><a href="http://lh6.ggpht.com/-SYoMbOYIg7U/VCktw6ClKrI/AAAAAAAABhI/imziuXutJAI/s1600-h/image5.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-ct0677jMQgc/VCktykUfyfI/AAAAAAAABhQ/GitJ6tpx0cE/image_thumb3.png?imgmax=800" width="1607" height="852" /></a></p> <p>Few points to note about the tool:</p> <ul> <li>You can only create the spcolor file </li> <li>Though you can use background image to test the style in the tool, it’s for preview only. The background image will not be included in the spcolor file. </li> <li>It’s quite unfortunate that there’s no user manual or documentation on how to use the tool. However there’s some videos available online, you can check. </li> </ul> <p> </p> <p> </p> <h5><u>Font Scheme</u></h5> <p>Font scheme defines the fonts to be used in different section of SharePoint site – navigation, heading, body etc when the theme will be applied. Most of the time you don’t need new font scheme. However if needed, the easiest way of creating a new font scheme is copy an existing one – for example ‘15/Template/Layouts/default.spfont’. If you don’t need custom font scheme as part of the theme, you don’t need to develop a custom font scheme.</p> <p> </p> <h5><u>Background Image</u></h5> <p>As part of the theme you can specify a background image that will used when the theme will be applied. Using background image is not quite common in SharePoint sites though.</p> <p> </p> <h5><u>Master Page</u></h5> <p>A theme can be associated with master page – <font style="background-color: #ffff00">but it doesn’t mean if theme is applied to a site, the master page will be changed too</font>. Rather, the master page will be used for previewing the theme. You can view the theme preview by navigating to Site Settings => Change the look, or browsing “<a title="http://sohel.dev.local/_layouts/15/designgallery.aspx" href="http://{siteurl}/_layouts/15/designgallery.aspx">http://{siteurl}/_layouts/15/designgallery.aspx</a>”. However, for custom theme if you specify a custom master page, then the master page should have a preview file associated, otherwise you will not see the theme in this design gallery.</p> <p> </p> <h4>Theme - Development/Deployment</h4> <p>I’ve provided a <font style="background-color: #ffff00"></font><a href="http://1drv.ms/1DQu1pO" target="_blank">sample Visual Studio solution</a><font style="background-color: #ffff00"></font> that shows how to develop a theme-based branding and deploy it. You can find code details from MSDN at <a title="http://msdn.microsoft.com/en-us/library/office/jj927175(v=office.15).aspx" href="http://msdn.microsoft.com/en-us/library/office/jj927175(v=office.15).aspx">http://msdn.microsoft.com/en-us/library/office/jj927175(v=office.15).aspx</a>. However, simply developing, deploying and applying themes include the following steps:</p> <ul> <li><strong><u>Uploading files</u></strong>: You can upload your files as SharePoint modules(themes spcolor, spfonts, master pages etc.). In your visual studio solutions add these files as modules and as you deploy the solution the files will be uploaded in appropriate locations. </li> <li><strong><u>Install Theme</u></strong>: You need to create list items in ‘design catalog’ with populating different properties like theme url, order, title etc. Creating this list item will make the theme available in the design gallery at <a title="http://sohel.dev.local/_layouts/15/designgallery.aspx" href="http://{siteurl}/_layouts/15/designgallery.aspx">http://{siteurl}/_layouts/15/designgallery.aspx</a> </li> <li><strong><u>Apply theme</u></strong>: If you would like to apply them when the feature is activated, you can apply the theme on feature activation. Alternatively you can apply theme manually from Site settings. In the sample solution, I’ve installed two themes (BrandingTestLight and BrandingTestDark) but only activated the dark theme on feature activation.</li> </ul> <p> </p> <p>To install theme, we need to create a list item in design catalog gallery as shown below:</p> <pre class="csharpcode">var themeItem = designCatalog.AddItem();
themeItem[<span class="str">"Name"</span>] = themeTitle;
themeItem[<span class="str">"Title"</span>] = themeTitle;
<strong>themeItem[<span class="str">"MasterPageUrl"</span>] = <span class="kwrd">new</span> SPFieldUrlValue(masterUrl);
</strong>themeItem[<span class="str">"ThemeUrl"</span>] = <span class="kwrd">new</span> SPFieldUrlValue(Web.Site.ServerRelativeUrl.TrimEnd(<span class="str">'/'</span>) + <span class="str">"/_catalogs/theme/15/"</span> + themeName);
themeItem[<span class="str">"DisplayOrder"</span>] = displayOrderCounter;
themeItem.Update();</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>In the code snippet above, Master page URL is only for displaying purpose. In my sample application I’ve used seattle.master. This is because whichever master page you use, the master page will have to have a ‘preivew’ file. Since it’s only for display purpose and seattle master page has a preview file, I’ve reused the same preview instead of creating a custom preview of my own for my custom master page. However, if you would like to create a custom preview for your master page you can see more details at <a title="http://msdn.microsoft.com/en-us/library/office/jj927173(v=office.15).aspx" href="http://msdn.microsoft.com/en-us/library/office/jj927173(v=office.15).aspx">http://msdn.microsoft.com/en-us/library/office/jj927173(v=office.15).aspx</a></p>
<p> </p>
<p> </p>
<p>To apply theme, you need to apply theme by using ‘Theme.ApplyTo’ method. However, there’s more. In the theme catalog (<a title="http://sohel.dev.local/_catalogs/design/AllItems.aspx" href="http://{sitecollection}/_catalogs/design/AllItems.aspx">http://{sitecollection}/_catalogs/design/AllItems.aspx</a>), you will find a list item with title ‘current’ as shown below. You need update the current theme - list item also as you can see in the sample solution provided.</p>
<p><a href="http://lh5.ggpht.com/-ipu_zJpHtWM/VCktz_0QmUI/AAAAAAAABhY/EWWp4sZPK1M/s1600-h/image%25255B4%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-ZCzY2GQ7N8s/VCkt0yoyPsI/AAAAAAAABhg/HYA9_oHOyGQ/image_thumb%25255B1%25255D.png?imgmax=800" width="1262" height="653" /></a></p>
<p> </p>
<h4>Download the code</h4>
<p>The sample solution I’ve uploaded <a href="http://1drv.ms/1DQu1pO" target="_blank">is available here</a> <font style="background-color: #ffff00"></font>. The sample solution adds two themes (BrandingTestLight and BrandingTestDark)  and a custom master page. Once you deploy the sample WSP, there’ll be a Web scoped feature “SharePoint Branding - Theme” will be available. Activating and deactivating the feature will deploy the themes and custom master pages, modify the default and custom master page, apply the dark theme.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-54028967345530464622014-06-22T10:30:00.001+07:002014-08-30T09:28:17.917+07:00SharePoint: Access large list<p>SharePoint list throttling limits to access maximum 5000 items through view/query. However your list can hold as much as 30,000,000 items but you can’t access more than 5000 items at once by view or query. But I’ve seen scenarios where list items goes millions in a year. So accessing large list having more than 5000 items not very rare in real life. </p> <p><strong>But have you ever asked yourself, why the limit is 5000 items? </strong> <br />The real limit of 5000 items is related to SQL server. I’m not a SQL server expert but let me try to explain as a non-SQL server expert – “If a SQL query returns more than 5000 items, SQL server locks the entire table – which will affect other queries on the table”. </p> <p>So as a SharePoint expert you might need to be in a situation where you need to work with large list (having more than 5000 items). However, there’s few options you have when you need to access large list. I’ll explain different options with pros and cons.</p> <p> </p> <h4>Option 1: Override the throttling limit (Less preferable)</h4> <p>You can override the throttling limit from web application settings or through code. I would not suggest to do it from web application as it’ll be applied throughout the web application, instead if you querying your list then you can override the setting as shown below:</p> <pre class="csharpcode">SPQuery spqry = <span class="kwrd">new</span> SPQuery();
spqry.QueryThrottleMode = SPQueryThrottleOption.Override;</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>The easy thing about this approach is that you don’t need to go through any complexity of writing complex code but downside is your query is taking excessive resources affecting other users. Points to note:</p>
<ul>
<li>Easy to use, as you don’t need to include any complexity in your code if you are using SPQuery. If your list views return more than 500 items, the views will not fail </li>
<li>Also this approach will send a single (possibly) SQL query that will return all items </li>
<li>However, other users browsing the site will find the site slow – as the full table lock will be applied in SQL server delaying other users request to be queued </li>
<li>If you are loading all of the items in memory, then your server should be able to handle the items </li>
<li>You can override the throttling limit, if your server is able to handle all the items in memory and you are executing your script during off-peak hour. I would prefer overriding the throttling limit, if, for example, I’m moving all data for archiving during off peak hour. More specifically, if you need to run the script periodically or once during off-peak hour then you may be override the throttling limit. </li>
</ul>
<p> </p>
<h4>Option 2: Access less than 5000 items Iteratively</h4>
<p>With this approach, you don’t override the SharePoint throttling limit (always preferable). Rather you loop through and access less than 5000 items on each iteration (say, 2000 items per iteration). The following block shows the idea:</p>
<pre class="csharpcode">var list = web.Lists[listName];
var maxItemId = list.Items[list.ItemCount - 1].ID; <span class="rem">//get max item id Or use below code to get max id using CAML</span>
<span class="rem">//spquery.RowLimit = 1;</span>
<span class="rem">//spquery.Query = "<OrderBy><FieldRef Name='ID' /></OrderBy>";</span>
var startIndex = 1;
<span class="kwrd">const</span> <span class="kwrd">int</span> processByCount = 4000; <span class="rem">//max no of items to be returned by spquery</span>
var endIndex = startIndex + processByCount;
<span class="kwrd">while</span> (startIndex < maxItemId)
{
var query = <span class="kwrd">new</span> SPQuery
{
Query = <span class="kwrd">string</span>.Format(<span class="str">@"<Where>
<And>
<Geq><FieldRef Name='ID' /><Value Type='Counter'>{0}</Value></Geq>
<Leq><FieldRef Name='ID' /><Value Type='Counter'>{1}</Value></Leq>
</And>
</Where>"</span>, startIndex, endIndex)
};
var items = web.Lists[<span class="str">"ListName"</span>].GetItems(query);
<span class="rem">//process items to convert to CSV</span>
startIndex = endIndex + 1;
endIndex = startIndex + processByCount;</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>The above approach is a good option for querying items through SPQuery. However, for list view, you need to modify your views to make sure the view doesn’t return more than 500 items. Points to note:</p>
<ul>
<li>You need to modify your existing views so that they don’t return more than 5000 items. </li>
<li>Once you modify your list views (as well as change the code to access less than 5000 items), the queries/views will have less affect on other live users. </li>
<li>However, you need to modify your existing code (or new code) to use the pattern to access not more than 5000 items. </li>
<li>Also for each loop, you will send a SQL query that will return the items. </li>
</ul>
<p> </p>
<h4>Option 3: Use ContentIterator</h4>
<p>SharePoint Server provides an API to access individual items using ‘<a href="http://msdn.microsoft.com/en-us/library/ff798376.aspx" target="_blank">ContentIterator</a>’. ContentIterator is kind of complete API for processing large list items. Points to note:</p>
<ul>
<li>The API has full capabilities of handling different scenarios </li>
<li>And the API is available in Office Server version not in Foundation. </li>
</ul>
<p> </p>
<h4>Conclusion</h4>
<p>Overriding throttling limit is in web application is the last option I would suggest. However overriding throttling limit through SPQuery can be used if you are running your query during off-peak hour and possibly one time. Option 2 of ‘Iteratively accessing less than 5000 items’ is more suitable as you can control how many items you would like to access on each request. ContentIterator is the preferable way, if you are using Server version of SharePoint. </p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-86965580999991335702014-05-13T18:01:00.001+07:002014-05-13T18:01:21.349+07:00SharePoint: Safe Control Entry using elements file<p>Recently I’ve discovered that it’s possible to add safe control entries through elements.xml file. To do this, add an elements.xml file (or use an existing xml file). Then select the elements.xml file and open the properties window as shown below:</p> <p><a href="http://lh5.ggpht.com/-POkImRT0jkA/U3H7cvp5n4I/AAAAAAAABbo/YFkenFF7T58/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-sOKbMt1lG8M/U3H7d9GfOLI/AAAAAAAABbw/GQ3tgqucOpE/image_thumb%25255B1%25255D.png?imgmax=800" width="499" height="208" /></a> </p> <p>Then click the ... button next to (Safe Control Entries) as shown in the above image. Then in the safe control entries dialog click ‘Add’ and edit the namespace as shown below:</p> <p><a href="http://lh3.ggpht.com/-VKxcSzO3NUQ/U3H7eo7TV2I/AAAAAAAABb4/uuClhwm3QA8/s1600-h/image%25255B7%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh4.ggpht.com/-mYx2Pxyfkpg/U3H7fs90P3I/AAAAAAAABcA/G3ijOUXL14k/image_thumb%25255B3%25255D.png?imgmax=800" width="726" height="410" /></a> </p> <p></p> <p>Finally, add the element xml file to a web/site scoped feature. As you will deploy the WSP, the safe control entry will be added in web.config file.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-67860738534550882222013-11-17T18:30:00.000+07:002013-12-04T20:59:03.544+07:00SharePoint 2013: Optimize your development Environment<p>SharePoint 2013 demands more resources – especially more memory. When we need to setup a SharePoint 2013 environment we can optimize resource usage in the development server by provisioning/configuring required services as well as following some other guidelines listed in this post.</p> <p> </p> <h4>Search Service Applications</h4> <p>Search Service is EXTREMELY resource hungry. noderunner process (Search Service process for crawling/indexing) is widely known for it’s resources usage footprint. In case you don’t need search service in your development server, you can delete the service application or at least stop the service. If you need to use the search service from time to time, you can keep the search service application running but stop the search service. However, <font color="#ff0000">if you try to stop the search service from windows service, you will find the service will be started again by SharePoint</font>. The correct way to stopping service is from Central admin as shown below:</p> <p><a href="http://lh5.ggpht.com/-ryeweYzHpNY/Un5In_zrlvI/AAAAAAAABU4/mQBV1fHdDRs/s1600-h/image%25255B7%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-Z99N2DcMsf8/Un5IoiwN-5I/AAAAAAAABVA/aakkowOA07I/image_thumb%25255B3%25255D.png?imgmax=800" width="1052" height="775" /></a> </p> <p> </p> <p>If you need the search service components (crawling/indexing) on development server, you can reduce the performance level by running the following command in SharePoint PowerShell. More information available at <a href="http://technet.microsoft.com/en-us/library/ff608126.aspx">http://technet.microsoft.com/en-us/library/ff608126.aspx</a>.</p> <p><strong><em>Set-SPEnterpriseSearchService -PerformanceLevel Reduced </em></strong></p> <p>You can also control the noderunner memory consumption by changing ‘<em><strong>memoryLimitMegabytes</strong></em>’ in the config file “<em><strong>C:\Program Files\Microsoft Office Servers\15.0\Search\Runtime\1.0\noderunner.exe.config</strong></em>”. Please remember, changing the value to too low might cause the search service to fail.</p> <p> </p> <p> </p> <h4>Provision Required Service Applications only</h4> <p>If you install SharePoint using Installation wizard, different service applications are installed but you many not need all of these service applications. From Central admin you can delete unnecessary Service applications as well as stop services. As you can see below</p> <p> </p> <p> </p> <h4>Stop unnecessary Web Application</h4> <p>Even web application running in your development environment will create w3wp process (if a separate application pool is used) or at least use resources. So if you don’t nee a web application for time being, you can stop the web application as well as related application pool from IIS Manager.</p> <p> </p> <p> </p> <h4>Visual Studio IntelliTrace</h4> <p>If you use Visual Studio debugging in the server and your Visual Studio supports IntelliTrace and the feature is enabled, you can disable the option. That might improve your debugging experience. More information on how to enable/disable the feature can be found at: <a href="http://msdn.microsoft.com/en-us/library/dd264948(v=vs.100).aspx">http://msdn.microsoft.com/en-us/library/dd264948(v=vs.100).aspx</a></p> <h4> </h4> <h4>Multiple Disk Drive</h4> <p>If you have configured multi-server farm, you can keep some servers in another disk drive. For example, I’ve a multi-server (4 servers – AD, SQL, WFE and App) farm and I’ve kept two servers in my external USB3 supported external drive. So rather than four server vying for the same disk access, two are vying for internal disk access and other two are vying for external disk. </p> <p>Even if are running a single server farm, you can use an external SSD drive (or USB3) for better I/O throughput. Especially if you can move your database files in an external drive, you will experience much better performance.</p> <p> </p> <h4>Tracing Service</h4> <p>SharePoint uses a windows Service ‘SharePoint Tracing Service’ for logging. sometimes, like during deployment, you will find the log file is growing few hundreds megabytes in short time. So tracing service might take a bit role in performance. If you don’t need the log file for a period of time, you can disable the windows service. During development I usually disable the service and when I need to see the log file, I enable the service.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-66102589176661397752013-10-27T10:50:00.000+07:002013-10-27T10:50:46.026+07:00Upgrade SharePoint 2010 Visual Studio Solution to SharePoint 2013<p>With every new version of SharePoint, we need to upgrade our Visual Studio solution. There’s no easy way or tool out there that can automate these upgrade. So I’ll just describe few points you need to consider when you’ll upgrade the Visual Studio 2010 project for SharePoint 2010 to Visual Studio 2012 project for SharePoint 2013. First of all, you need to upgrade your Visual Studio pre-VS2012 solution to Visual Studio 2012.</p> <h4>Change Target .NET Framework</h4> <p>SharePoint 2010 uses .Net Framework 3.5 with SharePoint 2013 uses .Net Framework 4.5. So you need to change the target framework for the project. To change the target framework version, unload the project and then edit the project file in Visual Studio and change the property as shown below: <br /></p> <pre class="csharpcode"><span class="kwrd"><</span><span class="html">TargetFrameworkVersion</span><span class="kwrd">></span>v4.5<span class="kwrd"></</span><span class="html">TargetFrameworkVersion</span><span class="kwrd">></span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<h4> </h4>
<h4>Change SharePoint Version</h4>
<p>Unload the project and edit in Visual Studio, then add/edit the section to ensure the following entry near to the <TargetFrameworkVersion></p>
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">TargetOfficeVersion</span><span class="kwrd">></span>15.0<span class="kwrd"></</span><span class="html">TargetOfficeVersion</span><span class="kwrd">></span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Then load the project and replace all SharePoint 2010 specific DLLs with SharePoint 2013 specific DLLs (version 15). Also find out any reference of SharePoint 2010 DLLs/Controls  version ‘14.0.0.0’ and replace with ‘15.0.0.0’</p>
<p> </p>
<h4>Change Generic Setup Path in code</h4>
<p>In SharePoint 2013, you can deploy your solution in SharePoint 2010 more or SharePoint 2013 mode or both. For example to deploy your solution to both 2010 and 2013 mode, you can use the following command:</p>
<p><strong><em>Install-SPSolution -Identity my_solution.wsp -GACDeployment -CompatibilityLevel {14,15}</em></strong></p>
<p>If you skip the CompatibilityLevel (and we usually skip), then the solution is deployed default compatibility level included in the WSP manifest file – which is based on Visual Studio project’s target SharePoint Version. But since we are targeting to upgrade Visual Studio solution to SharePoint 2013, we need to make sure code looks for artifacts in 15 hive, instead of 14 hive. To ensure that code looks in 15 hive, we need to find all use of ‘SPUtility.GetGenericSetupPath()’ and need to replace it with ‘SPUtility.GetVersionedGenericSetupPath()’ passing parameter 15 as shown below:</p>
<p><strong><em>SPUtility.GetVersionedGenericSetupPath(‘/_Layouts/myproject/script/test.js’,15)</em></strong></p>
<p>Note – If you are still deploying your solution in compatibility 14 mode, then you should also replace the ‘GetGenericSetupPath()’ with ‘GetVersionedGenericSetupPath()’ passing parameter 14, but instead of hardcoding the version inline, you can use a constant so that you can replace the version number in one place to change it to 15. You can use constant ‘Microsoft.SharePoint.Utilities.SPUtility.ContextCompatibilityLevel’ which returns the current compatibility level of the SPSite. Your code then will look like:</p>
<p><strong><em>SPUtility.GetVersionedGenericSetupPath(‘/_Layouts/myproject/script/test.js’,Microsoft.SharePoint.Utilities.SPUtility.ContextCompatibilityLevel)</em></strong></p>
<p> However, if you want to use the same code both for SharePoint 2010 and SharePoint 2013, then you can code block like below to run code in different version of SharePoint:</p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<pre class="csharpcode"><span class="rem">//if SharePoint site collection is running in 2013 (15) mode</span>
<span class="kwrd">if</span> (SPUtility.ContextCompatibilityLevel==SPUtility.CompatibilityLevel15)
{
<span class="rem">//Code needs to be executed in SharePoint 2013</span>
}
<span class="kwrd">else</span> <span class="kwrd">if</span> (SPUtility.ContextCompatibilityLevel==14)
{
<span class="rem">// Code needs to executed in SharePoint 2010</span>
}
<span class="rem">//You can also use SPSite.CompatibilityLevel to find out site collection compatibiltiy mode</span></pre>
<h4>Change Reference to Layouts, ControlTemplates</h4>
<p>Finally all references to ‘_Layouts/’ and ‘_ControlTemplates/’ needs to be changed to ‘_Layouts/15/’ and ‘_ControlTemplates/15/’ to ensure the artifacts are loaded from 15 hive. Either SharePoint will try to load files from 14 hive. However if you deploying the solution in SharePoint 2010 mode, (compatibility level is 14), then you don’t need to update the reference.</p>
<p> </p>
<h4>Conclusion</h4>
<p>After making all the above changes, finally compile the solution. However, my suggestion would be to deploy the WSP in SharePoint 2010 mode first, test the deployment and adjust/modify code to comply with SharePoint 2010 object model. Once you are comfortable with changes, then upgrade code as described in the post and then deploy/test.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com1tag:blogger.com,1999:blog-1804865242850018128.post-11946060999655920232013-10-13T16:28:00.000+07:002013-10-13T16:49:17.752+07:00SharePoint Suite/Chrome Control<p>SharePoint 2013 or Office 365 introduced a new ribbon on the top of the page known as Suite Control as shown below (‘SharePoint’ text): <br /><a href="http://lh6.ggpht.com/-7BSs2FMvSvE/UjVzGk6CFaI/AAAAAAAABKA/PrIXhIrME1E/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-0L7soV1dCsc/UjVzHuvc1rI/AAAAAAAABKI/MANtfSk8BGQ/image_thumb%25255B1%25255D.png?imgmax=800" width="781" height="43" /></a> <br />However, we may want to control the text to appear in the suite control and how they will appear. I’ll explain how to put static text as well as dynamic text in the suite control. For example you may want to show your environment name like ‘DEV’, ‘Test’.</p> <p> </p> <h4>Static Content</h4> If you would like to put just some static text replacing ‘SharePoint’ or ‘Office 365’ you can do so in few different ways that are described below: <br /> <h5>Modify using PowerShell</h5> You can modify the text using PowerShell and apply your own static text. You can apply text to web application level as shown below: <br /> <pre class="csharpcode">$webApplication = Get-SPWebApplication -Identity <span class="str">"http://web-application-url"</span>
$webApplication.SuiteBarBrandingElementHtml = <span class="str">'<div class="ms-core-brandingText">My Text</div>'</span>
$webApplication.Update()</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>
<br /><span style="color: red">This approach will work for whole web application but if you need different text in different sites, you may not be interested in this approach. Also for Office 365, you will not have these PowerShell command available</span>. </p>
<p> </p>
<h5>Modify through MasterPage</h5>
<p>However, if you don’t have access to PowerShell (as in Office 365, you have limited PowerShell access), you can modify master page to edit the text. <span style="color: red">For your information, if you are using HTML based master page design, then this approach will not work. For your information, in SharePoint 2013, you can develop HTML design first and then can convert the HTML to master page – hence HTML based master page design</span>. Open the default master page in your site using SharePoint Designer, or if you are using custom branding, open your custom master page in edit mode (either in SharePoint Designer or Visual Studio). Find a div with Id ‘suiteBar’ and there’s a delegate control inside the div with id ‘ID_SuiteBarBrandingDelegate’, set this delegate control visible property to ‘false’ (shown in the image below) as this will hide the default Chrome text. Then add your own chrome text in another div after the delegate control </p>
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">div</span> <span class="attr">class</span><span class="kwrd">="ms-core-brandingText"</span><span class="kwrd">></span>My Static Chrome Text<span class="kwrd"></</span><span class="html">div</span><span class="kwrd">></span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Finally the change will look like below:
<br />
<br /><a href="http://lh5.ggpht.com/-uySfIqsrbKk/UjVzISv6crI/AAAAAAAABKQ/6q7twoAXJbE/s1600-h/image%25255B7%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-GR_3NcYV_es/UjVzJf1ODkI/AAAAAAAABKY/991oTeLKThk/image_thumb%25255B3%25255D.png?imgmax=800" width="1075" height="308" /></a>
<br />However, if you are using HTML based master page design (where you have editing html page which is generating master page), this option will not work as the delegate control is not available in HTML file (rather available in master page file) and you are not supposed to edit the master page directly in HTML based master page design.
<br /></p>
<h5> </h5>
<h5>Modify Using JavaScript</h5>
If you want to use JavaScript to modify the text, edit your master page (or corresponding html file) and add the following script in the file.
<br />
<pre class="csharpcode"><script type=<span class="str">"text/javascript"</span>>
$(document).ready(<span class="kwrd">function</span> () {
ApplySuiteBranding(<span class="str">'My Text'</span>);
<span class="rem">//ApplySuiteBranding("<b>My Text</b>");</span>
<span class="rem">//ApplySuiteBranding("<b>My Text</b>");</span>
<span class="rem">//ApplySuiteBranding("<a href='http://abc.com'><img src='test.jpg' alt='icon'/></a>");</span>
});
<span class="kwrd">function</span> ApplySuiteBranding(htmlToApply) {
<span class="rem">//find for office 365 suite control</span>
<span class="kwrd">var</span> brandingBox = $(<span class="str">'#suiteBrandingBox'</span>);
<span class="kwrd">if</span> ($(brandingBox).length == 0) {
<span class="rem">//office 365 suite control not found, so it's SharePoint</span>
brandingBox = $(<span class="str">'#suiteBar'</span>).find(<span class="str">".ms-core-brandingText"</span>);
}
$(brandingBox).html(htmlToApply);
}
</script></pre>
<p><style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />For your information, the above script need to be applied in master page html file if you are using html based master page design. Otherwise apply the script in master page directly. Also you need to add reference to jQuery in the master page as the above script make use of jQuery Library. You can also modify the script to add dynamic text, like current site title by using ‘_spPageContextInfo.webTitle’. So this approach will enable developer to provide semi-dynamic text in the chrome – like web title or any other text that is accessible from jQuery/JavaScript.</p>
<p> </p>
<h4>Dynamic Content</h4>
<p>If you would like to modify the suite control text dynamically, for example add some dynamic navigation or apply different text in different site collection, then you need to create a delegate control. I would recommend this solution, if possible. Though it requires custom development/deployment but it gives you more flexibility and more robust solution. Let’s describe how to do that. I’m not going to explain it steps by steps as you can find a nice example of this at: <a href="http://blogs.msdn.com/b/findnavish/archive/2013/02/07/sharepoint-2013-customizing-suite-bar.aspx">http://blogs.msdn.com/b/findnavish/archive/2013/02/07/sharepoint-2013-customizing-suite-bar.aspx</a>.
<br /></p>
<p> </p>
<h4>Chrome Control in SharePoint 2013 Apps</h4>
<p>If you want to use Chrome Control in SharePoint apps, you can find more details on MSDN: <a href="http://msdn.microsoft.com/en-us/library/fp179916.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/fp179916.aspx</a>.
<br /></p>
<p> </p>
<h4>Conclusion</h4>
So in summary, if you are happy with static text for whole web application and have PowerShell command available, then use the option of PowerShell. However, if you don’t have access to PowerShell command (as in Office 365), then you can use JavaScript based or direct Master Page edit option described. Finally, if you want a decent and manageable solution (considering, you are deploying a custom WSP solution), you can use Delegate control which gives you more control to change text dynamically. Using JavaScript option will give you the option of adding static text as well as some dynamic text.
Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-35716243132981910922013-07-26T08:54:00.001+07:002013-10-27T09:04:54.660+07:00SharePoint 2013: Breadcrumb for list/libraryMaybe we’ve noticed the issue in SharePoint - if a list view webpart is added to page and user navigate to different folders in the list view, there’s no way for users to know current folder hierarchy. So basically breadcrumb for the list view webpart missing. If there would be a way of showing users the exact location in the folder hierarchy the user is current in (as shown in the image below), wouldn’t be that great? <br /><a href="http://lh5.ggpht.com/-7iurzvRdUjo/UfHW1pLJXAI/AAAAAAAABEk/h-JL0LuOigQ/s1600-h/image5.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; margin-left: 0px; display: inline; border-top-width: 0px; margin-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-aeOUm8xK88w/UfHW2ap1hiI/AAAAAAAABEs/JzUOYvrDjaE/image_thumb3.png?imgmax=800" width="539" height="199" /></a> <br /><b>Image 1: List view webpart with folder-navigation breadcrumb</b> <br /> <br /><b></b> <br />I’ll explain in the post how you can achieve this kind of folder navigation with minimum changes/customisation. <br /> <br /> <h4>Deployment</h4> Download the FolderNavigation.js file from <a href="http://code.msdn.microsoft.com/SharePoint-2013-Folder-661709eb" target="_blank">MSDN Code Gallery</a>. You can deploy the script either in Layouts folder (in case of full trust solutions) or in Master Page gallery (in case of SharePoint Online or full trust). I would recommend to deploy in Master Page Gallery so that even if you move to cloud, it works without modification. If you deploy in Master page gallery, you don’t need to make any changes, but if you deploy in layouts folder, you need to make small changes in the script which is described in section ‘Deploy JS Link file in Layouts folder’. <br /> <br /> <h5><u>Option 1: Deploy in Master Page Gallery (Suggested)</u></h5> If you are dealing with SharePoint Online, you don’t have the option to deploy in Layouts folder. In that case you need to deploy it in Master page gallery. <b><u><span style="color: red">Note, deploying the script in other libraries (like site assets, site library) will not work, you need to deploy in master page gallery</span></u></b>. To deploy in master page gallery manually, please follow the steps: <br /> <ol> <li>Download the js file from <a href="http://code.msdn.microsoft.com/SharePoint-2013-Folder-661709eb" target="_blank">MSDN Code Gallery</a>. </li> <li>Navigate to Root web => site settings => Master Pages (under group ‘Web Designer Galleries’). </li> <li>From the ‘New Document’ ribbon try adding ’JavaScript Display Template’ and then upload the FolderNavigation.js file and set properties as shown below: <br /><a href="http://lh3.ggpht.com/-5UhuSugi8QI/UfHW4Trsa_I/AAAAAAAABFE/_r6PEh--Ux0/s1600-h/image17.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-gi-lXGfl5uw/UfHW5GYg6CI/AAAAAAAABFM/yZpPw7WTFOg/image_thumb9.png?imgmax=800" width="635" height="637" /></a> <br /><b>Image 2: Upload JS file to Master Page Gallery </b></li> </ol> In the above image, we’ve specified the content type to ‘JavaScript Display Template’, ‘target control type’ to view to use the js file in list view. Also I’ve set target scope to ‘/’ which means all sites and subsites will be applied. If you have a site collection ‘/sites/HR’, then you need to use ‘/Sites/HR’ instead. You can also use List Template ID, if you need. <br /> <br /> <h5><u>Option 2: Deploy JS Link file in Layouts Folder</u> </h5> If you are deploying the FolderNavigation.js file in Layouts folder, you need to make small changes in the downloaded script’s RegisterModuleInti method as shown below: <br /> <pre class="csharpcode">RegisterModuleInit(<span class="str">'FolderNavigation.js'</span>, folderNavigation);</pre>
In this case the ‘RegisterModuleInit’ first parameter will be the path relative to Layouts folder. If you deploy your file in path ‘/_Layouts/folder1’, the then you need to modify code as shown below:
<br />
<pre class="csharpcode">RegisterModuleInit(<span class="str">'Folder1/FolderNavigation.js'</span>, folderNavigation);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />If you are deploying in other subfolders in Layouts folder, you need to update the path accordingly. What I’ve found till now, you can only deploy in Layouts and Master page gallery. But if you find deploying in other folders works, please share.
<br />
<br />
<h4>Use The JS File in List View WebPart</h4>
Once you deploy the FolderNavigation.js file, you can start using it in list view webpart. Edit the list view web part properties and then under ‘Miscellaneous’ section put the file url for JS Link as shown below:
<br /><a href="http://lh3.ggpht.com/-fwR6avlVoLw/UfHW5mDjIII/AAAAAAAABFU/7HIMfDd_hTA/s1600-h/image21.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-pLLtpWfVWOY/UfHW6a9zWwI/AAAAAAAABFc/KWItl6Lgn-4/image_thumb11.png?imgmax=800" width="403" height="500" /></a>
<br /><b>Image 3: JS Link for list view webpart</b>
<br /><b></b>
<br />Few points to note for this JS Link:
<br />
<ul>
<li>if you have deployed the js file in Master Page Gallery, You can use ~site or ~SiteCollection token, which means current site or current site collection respectively. </li>
<li>If you have deployed in Layouts folder, you need to use corresponding path in the JS Link properties. For example if you are deploying the file in Layouts folder, then use ‘/_layouts/15/FolderNavigation.js’, if you are deploying in ‘Layouts/Folder1’ then, use ‘/_layouts/15/Folder1/FolderNavigation.js’. </li>
</ul>
<br />
<h4>How it works?</h4>
<p>If you are interested how it works, you can carry on reading, either move to deployment section. Basically I’ve utilized the SharePoint 2013 Client Side Rendering (CSR) concept. If you are not familiar with this CSR, you can get the basic idea by Googling. Simply, CSR allows us to customize the rendering of SharePoint fields using JavaScript. I’ve developed a client side rendering JavaScript file which is shown below:</p>
<pre class="csharpcode"><span class="rem">///Author: Sohel Rana</span>
<span class="rem">//Version 1.2</span>
<span class="rem">//Last Modified on 27-Oct-2013</span>
<span class="rem">//Version History:</span>
<span class="rem">// 1. Added</span>
<span class="rem">// 2. Fixed the bug 'Filtering by clicking on field title would result duplicate navigation link'</span>
<span class="rem">// 3. Fixed the bug 'breadcrumb title always lowercase'. Now breadcrumb title is as like the folder name in the library even with case (lower/upper)</span>
<span class="rem">//replace query string key with value</span>
<span class="kwrd">function</span> replaceQueryStringAndGet(url, key, value) {
<span class="kwrd">var</span> re = <span class="kwrd">new</span> RegExp(<span class="str">"([?|&])"</span> + key + <span class="str">"=.*?(&|$)"</span>, <span class="str">"i"</span>);
separator = url.indexOf(<span class="str">'?'</span>) !== -1 ? <span class="str">"&"</span> : <span class="str">"?"</span>;
<span class="kwrd">if</span> (url.match(re)) {
<span class="kwrd">return</span> url.replace(re, <span class="str">'$1'</span> + key + <span class="str">"="</span> + value + <span class="str">'$2'</span>);
}
<span class="kwrd">else</span> {
<span class="kwrd">return</span> url + separator + key + <span class="str">"="</span> + value;
}
}
<span class="kwrd">function</span> folderNavigation() {
<span class="kwrd">function</span> onPostRender(renderCtx) {
<span class="kwrd">if</span> (renderCtx.rootFolder) {
<span class="kwrd">var</span> listUrl = decodeURIComponent(renderCtx.listUrlDir);
<span class="kwrd">var</span> rootFolder = decodeURIComponent(renderCtx.rootFolder);
<span class="kwrd">if</span> (renderCtx.rootFolder == <span class="str">''</span> || rootFolder.toLowerCase() == listUrl.toLowerCase())
<span class="kwrd">return</span>;
<span class="rem">//get the folder path excluding list url. removing list url will give us path relative to current list url</span>
<span class="kwrd">var</span> folderPath = rootFolder.toLowerCase().indexOf(listUrl.toLowerCase()) == 0 ? rootFolder.substr(listUrl.length) : rootFolder;
<span class="kwrd">var</span> pathArray = folderPath.split(<span class="str">'/'</span>);
<span class="kwrd">var</span> navigationItems = <span class="kwrd">new</span> Array();
<span class="kwrd">var</span> currentFolderUrl = listUrl;
<span class="kwrd">var</span> rootNavItem =
{
title: <span class="str">'Root'</span>,
url: replaceQueryStringAndGet(document.location.href, <span class="str">'RootFolder'</span>, listUrl)
};
navigationItems.push(rootNavItem);
<span class="kwrd">for</span> (<span class="kwrd">var</span> index = 0; index < pathArray.length; index++) {
<span class="kwrd">if</span> (pathArray[index] == <span class="str">''</span>)
<span class="kwrd">continue</span>;
<span class="kwrd">var</span> lastItem = index == pathArray.length - 1;
currentFolderUrl += <span class="str">'/'</span> + pathArray[index];
<span class="kwrd">var</span> item =
{
title: pathArray[index],
url: lastItem ? <span class="str">''</span> : replaceQueryStringAndGet(document.location.href, <span class="str">'RootFolder'</span>, encodeURIComponent(currentFolderUrl))
};
navigationItems.push(item);
}
RenderItems(renderCtx, navigationItems);
}
}
<span class="rem">//Add a div and then render navigation items inside span</span>
<span class="kwrd">function</span> RenderItems(renderCtx, navigationItems) {
<span class="kwrd">if</span> (navigationItems.length == 0) <span class="kwrd">return</span>;
<span class="kwrd">var</span> folderNavDivId = <span class="str">'foldernav_'</span> + renderCtx.wpq;
<span class="kwrd">var</span> webpartDivId = <span class="str">'WebPart'</span> + renderCtx.wpq;
<span class="rem">//a div is added beneth the header to show folder navigation</span>
<span class="kwrd">var</span> folderNavDiv = document.getElementById(folderNavDivId);
<span class="kwrd">var</span> webpartDiv = document.getElementById(webpartDivId);
<span class="kwrd">if</span>(folderNavDiv!=<span class="kwrd">null</span>){
folderNavDiv.parentNode.removeChild(folderNavDiv);
folderNavDiv =<span class="kwrd">null</span>;
}
<span class="kwrd">if</span> (folderNavDiv == <span class="kwrd">null</span>) {
<span class="kwrd">var</span> folderNavDiv = document.createElement(<span class="str">'div'</span>);
folderNavDiv.setAttribute(<span class="str">'id'</span>, folderNavDivId)
webpartDiv.parentNode.insertBefore(folderNavDiv, webpartDiv);
folderNavDiv = document.getElementById(folderNavDivId);
}
<span class="kwrd">for</span> (<span class="kwrd">var</span> index = 0; index < navigationItems.length; index++) {
<span class="kwrd">if</span> (navigationItems[index].url == <span class="str">''</span>) {
<span class="kwrd">var</span> span = document.createElement(<span class="str">'span'</span>);
span.innerHTML = navigationItems[index].title;
folderNavDiv.appendChild(span);
}
<span class="kwrd">else</span> {
<span class="kwrd">var</span> span = document.createElement(<span class="str">'span'</span>);
<span class="kwrd">var</span> anchor = document.createElement(<span class="str">'a'</span>);
anchor.setAttribute(<span class="str">'href'</span>, navigationItems[index].url);
anchor.innerHTML = navigationItems[index].title;
span.appendChild(anchor);
folderNavDiv.appendChild(span);
}
<span class="rem">//add arrow (>) to separate navigation items, except the last one</span>
<span class="kwrd">if</span> (index != navigationItems.length - 1) {
<span class="kwrd">var</span> span = document.createElement(<span class="str">'span'</span>);
span.innerHTML = <span class="str">'&nbsp;>&nbsp;'</span>;
folderNavDiv.appendChild(span);
}
}
}
<span class="kwrd">function</span> _registerTemplate() {
<span class="kwrd">var</span> viewContext = {};
viewContext.Templates = {};
viewContext.OnPostRender = onPostRender;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(viewContext);
}
<span class="rem">//delay the execution of the script until clienttempltes.js gets loaded</span>
ExecuteOrDelayUntilScriptLoaded(_registerTemplate, <span class="str">'clienttemplates.js'</span>);
};
<span class="rem">//RegisterModuleInit ensure folderNavigation() function get executed when Minimum Download Strategy is enabled.</span>
<span class="rem">//if you deploy the FolderNavigation.js file in '_layouts' folder use 'FolderNavigation.js' as first paramter.</span>
<span class="rem">//if you deploy the FolderNavigation.js file in '_layouts/folder/subfolder' folder, use 'folder/subfolder/FolderNavigation.js as first parameter'</span>
<span class="rem">//if you are deploying in master page gallery, use '/_catalogs/masterpage/FolderNavigation.js' as first parameter</span>
RegisterModuleInit(<span class="str">'/_catalogs/masterpage/FolderNavigation.js'</span>, folderNavigation);
<span class="rem">//this function get executed in case when Minimum Download Strategy not enabled.</span>
folderNavigation();</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p><style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style><style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style><style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br /><b>Code Snippet 1: Folder Navigation JavaScript</b>
<br />
<br />Let me explain the code briefly.
<br /></p>
<ul>
<li>The method ‘replaceQueryStringAndGet’ is used to replace query string parameter with new value. For example if you have url ‘<a href="http://abc.com/?key=value&name=sohel">http://abc.com?key=value&name=sohel</a>’  and you would like to replace the query string ‘key’ with value ‘New Value’, you can use the method like
<pre class="csharpcode">replaceQueryStringAndGet(<span class="str">"http://abc.com?key=value&name=sohel"</span>,<span class="str">"key"</span>,<span class="str">"New Value"</span>)</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></li>
<li>The function folderNavigation has three methods. Function ‘onPostRender’ is bound to rendering context’s OnPostRender event. The method first checks if the list view’s root folder is not null  and root folder url is not list url (which means user is browsing list’s/library’s root). Then the method split the render context’s folder path and creates navigation items as shown below:
<br />
<pre class="csharpcode"><span class="kwrd">var</span> item =
{
title: title,
url: lastItem ? <span class="str">''</span> : replaceQueryStringAndGet(document.location.href, <span class="str">'RootFolder'</span>, encodeURIComponent(rootFolderUrl))
};</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></li>
</ul>
<blockquote>As shown above, in case of last item (which means current folder user browsing), the url is empty as we’ll show a text instead of link for current folder.</blockquote>
<ul>
<li>Function ‘RenderItems’ renders the items in the page. I think this is the place of customisation you might be interested. Having all navigation items passed to this function, you can render your navigation items in your own way. renderContext.wpq is unique webpart id in the page. As shown below with the wpq value of ‘<u><i>WPQ2</i></u>’ the webpart is rendered in a div with id ‘WebPart<u><i>WPQ2</i></u>’.  <br />
<br /><a href="http://lh4.ggpht.com/-IX6GHyaazuI/UfHW3Fzu-NI/AAAAAAAABE0/tHaD4M-gFgo/s1600-h/image9.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-45DCBIEG3J4/UfHW3_as_PI/AAAAAAAABE8/AlRPA5d-_F4/image_thumb5.png?imgmax=800" width="761" height="718" /></a>
<br /><b>Image 4: How list view webpart is rendered</b>
<br />
<br />In ‘RenderItems’ function I’ve added a div just before the webpart div ‘WebPart<u><i>WPQ2</i></u>’ to put the folder navigation as shown in the image 1.
<br />  </li>
<li>In the method ‘_registerTemplate’, I’ve registered the template and bound the OnPostRender event. </li>
<li>The final piece is RegisterModuleInit. In some example you will find the function folderNavigation is executed immediately along with the declaration. However, there’s a problem with Client Side Rendering and Minimal Download Strategy (MDS) working together as <a href="http://blogs.technet.com/b/sharepointdevelopersupport/archive/2013/02/08/register-csr-override-on-mds-enabled-sharepoint-2013-site.aspx" target="_blank">described in here</a>. To avoid this problem, we need to Register foldernavigation function with RegisterModuleInit to ensure the script get executed in case of MDS-enabled site. The last line ‘folderNavigation()’ will execute normally in case of MDS-disabled site. </li>
</ul>
I’ve upload the js file in <a href="http://code.msdn.microsoft.com/SharePoint-2013-Folder-661709eb" target="_blank">MSDN code gallery</a>. Please download it from here.
<br />
<br />
<h4>Download</h4>
The JavaScript file is available in <a href="http://code.msdn.microsoft.com/SharePoint-2013-Folder-661709eb" target="_blank">MSDN gallery</a> for download.
<br />
<br />
<h4>Conclusion</h4>
The solution works for both SharePoint Server as well as SharePoint Online. Though I’ve shown manual process of deploying and updating the JS Link in webpart properties, you can develop powershell script to deploy the FolderNavigation. Few references might be useful:
<br />
<ul>
<li><a href="http://blogs.technet.com/b/sharepointdevelopersupport/archive/2013/02/08/register-csr-override-on-mds-enabled-sharepoint-2013-site.aspx" target="_blank">Register CSR-override on MDS enabled SharePoint 2013 site</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/jj220061.aspx" target="_blank">Custom Field Type with Client Side Rendering</a> </li>
<li><a href="http://www.idubbs.com/blog/2012/js-link-for-sharepoint-2013-web-partsa-quick-functional-primer/" target="_blank">JS Link for SharePoint 2013</a> </li>
</ul> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com78tag:blogger.com,1999:blog-1804865242850018128.post-61375788311595211882013-07-24T10:01:00.001+07:002013-07-24T10:02:47.842+07:00SharePoint Reporting Service and Bing Map – Unable to connect to Remote Server<p>We’ve RDL reports running in SharePoint using SQL Server Reporting Service. The reports were using Bing Map to display some BI information. Reports were working fine in our development box but as soon as we moved the reports in UAT, Bing map was failed to rendered and the error was ‘Unable to Connect to Remote Server’.</p> <p>After Googling it comes out that we need to configure proxy settings and we’ve a proxy in UAT. So we configured proxy settings for Reporting Service web.config file (which usually exists in Reporting Server location at Drive:\Program Files\Microsoft SQL Server\MSRS10_50.[instance name]\Reporting Services\ReportServer\web.config) as shown below. You need to add the following section in between <Configuration> section (possibly after </Runtime>):</p> <pre class="csharpcode"><span class="kwrd"><</span><span class="html">system.net</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">defaultProxy</span> <span class="attr">enabled</span><span class="kwrd">="true"</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">proxy</span> <span class="attr">bypassonlocal</span><span class="kwrd">="True"</span> <span class="attr">proxyaddress</span><span class="kwrd">="http://server:port"</span> <span class="kwrd">/></span>
<span class="kwrd"></</span><span class="html">defaultProxy</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">system.net</span><span class="kwrd">></span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>But it didn’t solve our problem. Still we were getting the error <strong>Unable to connect to remote server</strong>.</p>
<p> </p>
<h4>Solution</h4>
<p>After investigating it turned out that we also need to configure SharePoint Reporting Services Service Application’s web.config file. You can find the Reporting Service Application by browsing the ‘SharePoint Web Service’ in IIS as shown below (in SharePoint 2013 box):</p>
<p><a href="http://lh6.ggpht.com/-NRkRZbUgKG4/Ue9DjFMmVkI/AAAAAAAABEM/2aauCpbqiPA/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="image" src="http://lh3.ggpht.com/-7LuKP3Qy9DY/Ue9Dj1q0VfI/AAAAAAAABEU/C2nB-2eJy2w/image_thumb%25255B1%25255D.png?imgmax=800" width="679" height="413" /></a> </p>
<p><strong>Figure : SharePoint Service Application – SQL Server Reporting Services in IIS</strong></p>
<p> </p>
<p>So you need to configure the proxy settings for both:</p>
<ul>
<li>SQL Server Reporting Service (Drive:\Program Files\Microsoft SQL Server\MSRS10_50.[instance name]\Reporting Services\ReportServer\web.config) </li>
<li>as well as SharePoint Reporting Service Application’s web.config file (shown in above image).</li>
</ul> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-18660527221004511582013-07-19T14:44:00.000+07:002013-07-19T14:44:16.006+07:00SharePoint 2013: Browse and Upload Multiple Documents MissingSharePoint 2013 introduced new features with more user-friendly User Interface. But Maybe it’s not true for ‘Multiple Documents upload’. SharePoint 2013 deprecated upload multiple files with ‘file upload control’ as described in the <a href="http://support.microsoft.com/kb/2761257" target="_blank">Microsoft Support page</a>. Let’s take a look what it was in SharePoint 2010 and what’s we’re missing in SharePoint 2013.<br />
<br />
<h4>
SharePoint 2010 – Upload Multiple Documents Dialog</h4>
In SharePoint 2010, we are familiar with the following multiple upload control as shown below:<br />
<a href="http://lh3.ggpht.com/-t7rMBtkt6DU/UeFK-wyCirI/AAAAAAAABC0/5to00CBL87s/s1600-h/image%25255B3%25255D.png"><img alt="image" border="0" height="249" src="http://lh4.ggpht.com/-q2GUAIGmoaM/UeFK_-K338I/AAAAAAAABC8/jtmq5WG5mRc/image_thumb%25255B1%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="400" /></a><br />
<b>Image 1: SharePoint 2010 - Upload Multiple File</b><br />
<br />
The ‘Upload Multiple Documents’ option in SharePoint 2010 allows to drag and drop files but there’s also an option to browse files as shown below:<br />
<a href="http://lh6.ggpht.com/-h5IVG1hHv9k/UeFLAZzvtKI/AAAAAAAABDE/QU_PeQi0nXw/s1600-h/image%25255B11%25255D.png"><img alt="image" border="0" height="435" src="http://lh5.ggpht.com/-LNPvg_g701s/UeFLA6po-kI/AAAAAAAABDM/ux3aiTaSG3E/image_thumb%25255B5%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="671" /></a><br />
<b>Image 2: SharePoint 2010 ‘Upload Multiple Documents’ dialog with browse file option</b><br />
The ‘Browse for files instead’ option (as shown in the Image 2 above) would be last resort for users – where drag and drop would not work. But this option is missing now in SharePoint 2013.<br />
<br />
<h4>
SharePoint 2013 – Multiple Documents Upload Options</h4>
As described in <a href="http://support.microsoft.com/kb/2761257/en-us" title="http://support.microsoft.com/kb/2761257/en-us">http://support.microsoft.com/kb/2761257/en-us</a>, users have the two following options in SharePoint 2013 to upload multiple files:<br />
<ul>
<li>Windows Explorer View </li>
<li>Drag-n-Drop </li>
</ul>
The following image shows how the new ‘upload document’ ribbon control in SharePoint 2013 looks now:<br />
<a href="http://lh5.ggpht.com/-yZhnbD8oh80/UeFLBZJuRuI/AAAAAAAABDU/F0kbuVY_-7E/s1600-h/image%25255B19%25255D.png"><img alt="image" border="0" height="136" src="http://lh5.ggpht.com/-NoAIo3yxtbM/UeFLCJLXeOI/AAAAAAAABDc/CNd_OEV8oMU/image_thumb%25255B9%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="354" /></a><br />
<b>Image 3: Upload ribbon button in SharePoint 2013</b><br />
<br />
<b></b><br />
With ‘browse multiple files and upload’ deprecated in SharePoint 2013, Drag And Drop is the only way of uploading multiple files inside browser. Unfortunately the drag and drop will only work with IE9 (and later versions of IE) but not in IE8. Also some users might find drag-n-drop a bit difficult to deal with (need to open windows explorer, select the files, drag the files in Internet explorer and in a particular section).<br />
<br />So what options left for users who are using IE8? They can use other browsers like Chrome, FireFox etc. (nice way of using non-IE for browsing SharePoint) for drag and drop. Otherwise they can use Windows Explorer View. However Windows Explorer view may need minor configuration in users’ computers and might not work for Office 365. There’s no official explanation of why the ‘browse and upload multiple documents’ option is removed from SharePoint 2013 in the <a href="http://support.microsoft.com/kb/2761257" target="_blank">Microsoft Support page</a>.<br />
<br />It’s really disappointing to see the upload multiple files through file upload control gone in SharePoint 2013. Users who are using SharePoint 2013 and IE8, as well as they don’t have windows explorer view configured, they have only one option of using non-IE browsers. Also some users might find drag and drop a bit difficult to use. And Microsoft didn’t leave any choice for them.Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com1tag:blogger.com,1999:blog-1804865242850018128.post-35841635322748827242013-06-14T12:21:00.001+07:002013-07-14T10:38:45.245+07:00SharePoint 2013: Start Workflow with JavaScript Client Object Model<p>In SharePoint 2013, you can start a workflow with JavaScript Client Object Model. Basically SharePoint use JavaScript in out-of-the-box ‘start workflow’ pages. If you develop a new SharePoint 2013 workflow in Visual Studio and add a Initiation form, you will find JavaScript functions added to the Initiation Form to start workflow. The source code I’ve provided below is taken from the Initiation Form and presented with modification to work independently.</p> <pre class="csharpcode"><span class="rem">//dialog element to show during processing</span>
<span class="kwrd">var</span> dlg = <span class="kwrd">null</span>;
<span class="rem">//Subscription id - Workflow subscription id</span>
<span class="rem">//list item id for which to start workflow. If site workflow, then send null for itemId</span>
<span class="kwrd">function</span> StartWorkflow(subscriptionId, itemId) {
showInProgressDialog();
<span class="kwrd">var</span> ctx = SP.ClientContext.get_current();
<span class="kwrd">var</span> wfManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, ctx.get_web());
<span class="kwrd">var</span> subscription = wfManager.getWorkflowSubscriptionService().getSubscription(subscriptionId);
ctx.load(subscription, <span class="str">'PropertyDefinitions'</span>);
ctx.executeQueryAsync(
<span class="kwrd">function</span> (sender, args) {
<span class="kwrd">var</span> <span class="kwrd">params</span>= <span class="kwrd">new</span> Object();
<span class="rem">//Find initiation data to be passed to workflow.</span>
<span class="kwrd">var</span> formData = subscription.get_propertyDefinitions()[<span class="str">"FormData"</span>];
<span class="kwrd">if</span> (formData != <span class="kwrd">null</span> && formData != <span class="str">'undefined'</span> && formData != <span class="str">""</span>) {
<span class="kwrd">var</span> assocParams = formData.split(<span class="str">";#"</span>);
<span class="kwrd">for</span> (<span class="kwrd">var</span> i = 0; i < assocParams.length; i++) {
<span class="kwrd">params</span>[assocParams[i]] = subscription.get_propertyDefinitions()[assocParams[i]];
}
}
<span class="kwrd">if</span> (itemId) {
wfManager.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemId, <span class="kwrd">params</span>);
}
<span class="kwrd">else</span> {
wfManager.getWorkflowInstanceService().startWorkflow(subscription, <span class="kwrd">params</span>);
}
ctx.executeQueryAsync(
<span class="kwrd">function</span> (sender, args) {
closeInProgressDialog();
},
<span class="kwrd">function</span> (sender, args) {
closeInProgressDialog();
alert(<span class="str">'Failed to run workflow'</span>);
}
);
},
<span class="kwrd">function</span> (sender, args) {
closeInProgressDialog();
alert(<span class="str">'Failed to run workflow'</span>);
}
);
}<br />
<span class="kwrd">function</span> closeInProgressDialog() {
<span class="kwrd">if</span> (dlg != <span class="kwrd">null</span>) {
dlg.close();
}
}
<span class="kwrd">function</span> showInProgressDialog() {
<span class="kwrd">if</span> (dlg == <span class="kwrd">null</span>) {
dlg = SP.UI.ModalDialog.showWaitScreenWithNoClose(<span class="str">"Please wait..."</span>, <span class="str">"Waiting for workflow..."</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
}
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style><!--CRLF-->
<p><strong>Code Snippet 1: Start workflow </strong></p>
<p> </p>
<p>As shown in the above code example, you need to pass subscription id and item id. Everytime you associate workflow with list or site, you will get an association id for this association.To get an association id, go to the workflow settings page and then right click on workflow name and from the URL, you can find the subscription id as shown below:</p>
<p><a href="http://lh5.ggpht.com/-LFXF1qYSY1o/UbqocLBWF9I/AAAAAAAABB4/0VatiUcwNj4/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-typGEnHyHa0/Ubqocriu4HI/AAAAAAAABCA/cftfJmkkAJ8/image_thumb%25255B1%25255D.png?imgmax=800" width="856" height="531" /></a> </p>
<p><strong>Figure 1: Get the Workflow Association Id from Workflow Settings Page</strong></p>
<p> </p>
<p>If your workflow is Site Workflow (for your information, SharePoint 2013 workflow can run on a list item or for site), then pass null value for itemId. ‘FormData’ retrieved from workflow Subscription, will be passed to workflow initiation. But if you would like to pass your own additional parameters, you can do so as shown below:</p>
<div id="codeSnippetWrapper">
<pre class="csharpcode"><span class="kwrd">var</span> <span class="kwrd">params</span>= <span class="kwrd">new</span> Object();
<span class="rem">//Find initiation data to be passed to workflow.</span>
<span class="kwrd">var</span> formData = subscription.get_propertyDefinitions()[<span class="str">"FormData"</span>];
<span class="kwrd">if</span> (formData != <span class="kwrd">null</span> && formData != <span class="str">'undefined'</span> && formData != <span class="str">""</span>) {
<span class="kwrd">var</span> assocParams = formData.split(<span class="str">";#"</span>);
<span class="kwrd">for</span> (<span class="kwrd">var</span> i = 0; i < assocParams.length; i++) {
<span class="kwrd">params</span>[assocParams[i]] = subscription.get_propertyDefinitions()[assocParams[i]];
}
}
<span class="rem">//your custom parameters</span>
<span class="kwrd">params</span>[<span class="str">'mykey'</span>]=<span class="str">'this is custom value'</span>;</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></div>
<p><strong>Code Snippet 2: Passing workflow initiation parameters</strong></p>
<p> </p>
<p>Similarly, if you would like to get JavaScript to associate workflow, you can add a workflow in Visual Studio and then add a association from. In the association form, you will find related JavaScript to associate workflow using JavaScript Object Model.</p>
<p>Finally you can all the javascript function provided in code snippet 1, as shown below (subscription id with curly braces):</p>
<p>StartWorkflow(‘{guid}’, itemId)</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com5tag:blogger.com,1999:blog-1804865242850018128.post-26471367625014772882013-05-27T15:47:00.001+07:002013-05-27T15:47:54.511+07:00Programmatically Start SharePoint 2013 Workflow<p>SharePoint 2013 introduced a new set of API to work with new workflow model. In my <a href="http://ranaictiu-technicalblog.blogspot.com.au/2013/05/sharepoint-2013-workflow.html" target="_blank">previous post</a> I described how to access workflows associated with a list/list item and access workflow properties. In this post I’ll describe how to run SharePoint 2013 workflow programmatically.</p> <p>First you need to create instance of WorkflowServicesManager, then you need to find out the subscription (which actually represent the workflow association). Finally you can run the workflow with WorkflowInstance Service as shown below:</p> <pre class="csharpcode">var workflowServiceManager = <span class="kwrd">new</span> WorkflowServicesManager(web);
var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService();
<span class="rem">//get all workflows associated with the list</span>
var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByList(listId);
<span class="rem">//run all workflows associated with the list</span>
<span class="kwrd">foreach</span> (var workflowSubscription <span class="kwrd">in</span> subscriptions)
{
<span class="rem">//initiation parameters</span>
var inputParameters = <span class="kwrd">new</span> Dictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>>();
inputParameters.Add(<span class="str">"MyProperty"</span>, <span class="str">"MyValue"</span>);
workflowServiceManager.GetWorkflowInstanceService().StartWorkflowOnListItem(workflowSubscription, itemId, inputParameters);
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>In the StartWorkflowOnListItem, if you have any input parameters (which you usually pass from workflow initiation form), you can pass the input paramters as a dictionary. Otherwise, you can pass an empty dictionary. </p>
<p> </p>
<p>Similarly you can terminate or suspend workflows using Workflow Instance Service.</p>
<p>For your information, workflow will not run if you use an elevated web in WorkflowServicesManager. You need to make sure you are running the code with an user who is not system account and who has a user profile.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com16tag:blogger.com,1999:blog-1804865242850018128.post-39778440187611537802013-05-25T19:02:00.001+07:002013-05-25T19:04:02.199+07:00SharePoint 2013 Workflow: Programmatically Access Workflow Properties<p>SharePoint 2013 workflow introduced a new API to interact with SharePoint 2013 workflows. The old workflow API will not work for this new workflow model. The most basic API is available as part of the DLL (Microsoft.SharePoint.WorkflowServicesBase.dll) and the basic entry point for accessing workflow data is WorkflowServicesManager class. I’ll explain few uses of API but you can browse the API to find out more details usage.</p> <p> </p> <h4>Get all Workflows associated with a list</h4> <p>You need to create a new instance of WorkflowServiceManager and using the list id, you can ask WorkflowSubscriptionService to find all workflows associated with the list as shown below:</p> <pre class="csharpcode">WorkflowServicesManager workflowServiceManager = <span class="kwrd">new</span> WorkflowServicesManager(web);
var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService();
var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByList(listId);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>You can get subscription properties as shown below. If you association form has any custom properties, you can retrieve these property values by passing property name.</p>
<pre class="csharpcode"><span class="kwrd">foreach</span> (var subscription <span class="kwrd">in</span> subscriptions)
{
var assocationName = subscription.Name;
var propertyValue = subscription.GetProperty(<span class="str">"Property_Name"</span>);
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<h4> </h4>
<h4>Get Workflow Instance</h4>
<p>To get workflow instance details we need get the instance of WorkflowInstanceService from WorkflowServiceManager class as shown below:</p>
<pre class="csharpcode">WorkflowServicesManager workflowServiceManager = <span class="kwrd">new</span> WorkflowServicesManager(web);
var workflowInstanceService = workflowServiceManager.GetWorkflowInstanceService();
var workflowInstances = workflowInstanceService.EnumerateInstancesForListItem(listId, itemId);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Once we get the workflow Instance, we can get the instance properties as shown below. Any properties in Workflow Initiation form will also be available:</p>
<pre class="csharpcode"><span class="kwrd">foreach</span> (var instance <span class="kwrd">in</span> workflowInstances)
{
var propertyValue= instance.Properties[<span class="str">"Property_Name"</span>];
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>The table below shows few common properties, but you can find out more properties by debugging code:</p>
<table border="1" cellspacing="0" cellpadding="0" width="872"><tbody>
<tr>
<td valign="top" width="365">
<p><b>Property Name</b></p>
</td>
<td valign="top" width="505">
<p><b>Description</b></p>
</td>
</tr>
<tr>
<td valign="top" width="365">
<p>Microsoft.SharePoint.ActivationProperties.ContextListId</p>
</td>
<td valign="top" width="505">
<p>List Id</p>
</td>
</tr>
<tr>
<td valign="top" width="365">
<p>Microsoft.SharePoint.ActivationProperties.CurrentItemUrl</p>
</td>
<td valign="top" width="505">
<p>Current Item Url</p>
</td>
</tr>
<tr>
<td valign="top" width="365">
<p>Microsoft.SharePoint.ActivationProperties.InitiatorUserId</p>
</td>
<td valign="top" width="505">
<p>Initiator User login name, for example i:0#.w|domain\username</p>
</td>
</tr>
<tr>
<td valign="top" width="365">
<p>Microsoft.SharePoint.ActivationProperties.ItemId</p>
</td>
<td valign="top" width="505">
<p>List Item Id</p>
</td>
</tr>
</tbody></table>
<p> </p>
<h4>Send Custom Notification to Workflow</h4>
<p>In SharePoint 2013 workflow, there’s a activity ‘WaitForCustomEvent’. Using this activity you can keep your workflow wait for a custom event. In this activity you can pass the event name. To send the custom event to the workflow you can use workflow API as shown below. First you need to find out the workflow Instance.</p>
<pre class="csharpcode">WorkflowServicesManager workflowServiceManager = <span class="kwrd">new</span> WorkflowServicesManager(web);
var workflowInstanceService = workflowServiceManager.GetWorkflowInstanceService();
workflowInstanceService.PublishCustomEvent(workflowInstance, <span class="str">"CustomEventName"</span>, <span class="str">""</span>);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com23tag:blogger.com,1999:blog-1804865242850018128.post-37835361703536105322013-04-28T18:22:00.000+07:002013-05-29T12:41:26.097+07:00SharePoint 2013 Workflow: Use HttpSend Activity to call Custom SharePoint WCF ServiceSharePoint 2013 workflow are declarative workflow – means no C# code inside the workflow. All you have in declarative workflow, is predefined activities (or maybe your own custom activities). If you would like to do some very customized things to do in workflow (like verifying data in some external system), you can do so with a WCF service. And then from workflow, you can invoke the WCF. In this post I’ll explain how to create a WCF service and invoke it from workflow. I’ve uploaded the source code in MSDN Code Gallery. Please make sure you have March update for Workflow Manager and Service Bus 1.0 installed, unless the source code might not work properly.<br />
<br />
<h4>
Create a WCF Service</h4>
I had described once how to <a href="http://ranaictiu-technicalblog.blogspot.com.au/2011/09/sharepoint-2010-access-wcf-service-with.html" target="_blank">create a WCF service and use it with jQuery for SharePoint 2010</a> and I’ve created the WCF service based on this post. The workflow Service interface is given below:<br />
<pre class="csharpcode">[ServiceContract]
<span class="kwrd">public</span> <span class="kwrd">interface</span> IServiceForWorkflow
{
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, UriTemplate = <span class="str">"/GetData?instanceId={wfInstanceId}"</span>)]
WorkflowData GetWorkflowData(<span class="kwrd">string</span> wfInstanceId);
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, Method = <span class="str">"POST"</span>, RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, UriTemplate = <span class="str">"/SendEmail?toEmail={to}&emailSubject={subject}"</span>)]
<span class="kwrd">void</span> SendEmail(<span class="kwrd">string</span> to,<span class="kwrd">string</span> subject);
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />
<b>Code Snippet: Service Interface</b><br />
As shown in above code snippet, I’ve defined the service method endpoints in UriTemplate. In the UriTemplate, for example <i>/GetData?instanceId={wfInstanceId}</i>, the {wfInstanceId} value is mapped to GetWorflowData method parameter ‘<i>wfInstanceId</i>’. From workflow using HttpSend activity, the service can be invoked as ‘<i>http://serverurl/_vti_bin/ServiceFielName.svc/<i>GetData?instanceId={wfInstanceId}</i></i>”. The current site url is retrievable from Workflow Context using <i>LookupWorkflowContextProperty </i>activity. Image 1 shows how the HttpSend Activity is used to call the service method from workflow.<br />
<br />
<h4>
Create Workflow</h4>
For simplicity, I’ve created a list workflow and once you deploy you need to manually associate the workflow with list/library. You can create either site or list workflow in SharePoint 2013. And if you want you can associate your workflow later instead of development time – maybe through feature receiver. The workflow I’ve created is need to be started manually. To manage workflow development in better ways, I’ve grouped my workflow activities in few groups (parse context values, call wcf service, parse service data etc.) – each group is a sequence of actions.<br />
<br />
<b></b><br />
<b><u></u></b><br />
<b><u></u></b><br />
<b><u></u></b><br />
<b><u>Use HttPSend Activity to call WCF Service:</u></b><br />
To call WCF Service, you need to use HttPSend activity. In this activity you can configure HTTP Verb (GET, POST, MERGE etc.). Since our WCF service will return json data, we need to add two headers (accept and content-type) in the HTtPSend activity to support json data. Also you need to set authorization header to empty string to work properly. Please add the following headers in the HttPSend activity:<br />
<table border="1" cellpadding="2" cellspacing="0" style="width: 504px;"><tbody>
<tr>
<td valign="top" width="200">Accept</td>
<td valign="top" width="302">"application/json; odata=verbose"</td>
</tr>
<tr>
<td valign="top" width="200">Content-Type</td>
<td valign="top" width="302">"application/json; odata=verbose"</td>
</tr>
<tr>
<td valign="top" width="200">Authorization</td>
<td valign="top" width="302">“”</td>
</tr>
</tbody></table>
In the HttpSend activity, the service response returned can be stored in a variable of type DynamicValue. You can read more about DynamicValue at <a href="http://msdn.microsoft.com/en-us/library/windowsazure/jj193505(v=azure.10).aspx">http://msdn.microsoft.com/en-us/library/windowsazure/jj193505(v=azure.10).aspx</a>. The following image shows how you can pass different properties in HttpSend activity:<br />
<a href="http://lh3.ggpht.com/-PJhtar4y8tA/UX0EaMwN2SI/AAAAAAAABA0/FR8ITKxEt_M/s1600-h/image%25255B23%25255D.png"><img alt="image" border="0" height="746" src="http://lh4.ggpht.com/-sRm_5LKKSrw/UX0EbEFaWcI/AAAAAAAABA8/oCsrdnh-WfA/image_thumb%25255B11%25255D.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="796" /></a> <br />
<b>Image 1: HttpSend Activity in use</b><br />
In the above image, conetent-type and accept header is used to support json data whereas the ‘Authorization’ header is used for WCF service to be invoked properly from workflow. <br />
<br />
<b><u>Parse Service Response:</u></b><br />
In the code example provided as part of this post, a workflow variable “WorkflowData” is used to store the returned service response. To retrieve the dynamic data property you can use GetDynamicValueProperty<T> activity, passing the property name. If you have a collection of items returned from service, you can use foreach control block from workflow Toolbox and can apply the GetDynamicValueProperty for each item in foreach. The response from service is stored in a workflow property ‘<i>WorkflowData</i>’ as shown in image 1. The response from service is the object of the following type:<br />
<pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> WorkflowData
{
<span class="kwrd">public</span> <span class="kwrd">string</span> Subject { get; set; }
<span class="kwrd">public</span> <span class="kwrd">bool</span> SendEmail { get; set; }
<span class="kwrd">public</span> <span class="kwrd">string</span> EmailTo { get; set; }
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<br />
<b>Code Snippet: Workflow data returned from service</b><br />
<br />
The service response is of type ‘WorkflowData’ as defined in above code snippet. To read any property of the ServiceResponse variable (as shown in Image 1) which is of type WorkflowData, GetDynamicValueProperty<T> is used as shown below – where WorkflowData.SendEmail is parsed:<br />
<a href="http://lh4.ggpht.com/-HB9PlrNsnU8/UX0Eb4HvZhI/AAAAAAAABBE/1Wot92_v_6I/s1600-h/image%25255B27%25255D.png"><img alt="image" border="0" height="180" src="http://lh4.ggpht.com/-6cQNSiZP4Fg/UX0EcTtBr_I/AAAAAAAABBM/4GOpapqXhVQ/image_thumb%25255B13%25255D.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="779" /></a> <br />
<b>Image 2: Parse Service Response property ‘SendEmail’</b><br />
<br />
Finally in the workflow, based on the parsed value (SendEmail property), I’m updating the workflow status. <br />
<h4>
</h4>
<h4>
Download Source Code</h4>
I’ve uploaded the source code in MSDN code gallery. Please download the source code from <a href="http://code.msdn.microsoft.com/SharePoint-2013-Workflow-e14e0e7a" title="http://code.msdn.microsoft.com/SharePoint-2013-Workflow-e14e0e7a">http://code.msdn.microsoft.com/SharePoint-2013-Workflow-e14e0e7a</a><br />
<br />
<h4>
Conclusion</h4>
MSDN has good numbers of examples available to start with workflow. Let me give you some links to these examples that might be helpful:<br />
<ul>
<li><a href="http://code.msdn.microsoft.com/DynamicValue-Path-c84f9ade" target="_blank">Dynamic Value Path Evaluator</a>: Use this code example to understand how to parse the response from service </li>
<li><a href="http://code.msdn.microsoft.com/Workflow-Resource-Browser-a67b1d27" target="_blank">Workflow Resource Browser</a>: Browse workflow server resources </li>
</ul>
You can get more examples of workflow manager at <a href="http://msdn.microsoft.com/en-us/library/windowsazure/jj193482(v=azure.10).aspx">http://msdn.microsoft.com/en-us/library/windowsazure/jj193482(v=azure.10).aspx</a>. Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com20tag:blogger.com,1999:blog-1804865242850018128.post-46229457756090159622013-04-03T11:36:00.000+07:002013-04-03T11:37:49.720+07:00SharePoint 2013: Workflow Error ‘Cannot set unknown member’<p>I was trying to develop a workflow using Visual Studio 2012 for SharePoint 2013. When I was trying to publish the workflow i was getting the following exception:</p> <p><strong><font color="#ff0000">Microsoft.Workflow.Client.ActivityValidationException: Workflow XAML failed validation due to the following errors: <br />Cannot set unknown member 'LookupSPListItem.ItemId'. <br />HTTP headers received from the server………….</font></strong></p> <p>Then after googling i had found the hint in the <a href="http://social.msdn.microsoft.com/Forums/en-US/sharepointadminprevious/thread/46a868eb-a012-4148-8319-088d55671ae7" target="_blank">Microsoft Forum</a>.</p> <p> </p> <h4>Solution</h4> <p>Basically you need to re-register the workflow using a Powershell command like below. I think when any Workflow Manager or SharePoint update is installed in the server, these two components get out of sync and re-running the registration will sync both again.</p> <p><strong>Register-SPWorkflowService -SPSite "SiteURL" -WorkflowHostUri 'WorkflowHostURL'  -Force</strong></p> <p>Remember to mention Force switch. After the command, restart the Visual Studio or SharePoint Designer and hopefully the issue will be fixed.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com4tag:blogger.com,1999:blog-1804865242850018128.post-57963565056668850192013-03-17T10:39:00.000+07:002013-03-17T10:42:16.774+07:00SharePoint 2013: Use Twitter Bootstrap for SharePoint App development<p>If you have not heard of Bootstrap, it’s a CSS framework just like javaScript framework jQuery. Using Bootstrap, you can get various CSS classes that can be used in web design to make your web site looking consistent and impressive.</p> <h4>Introduction to Bootstrap</h4> <p>Bootstrap was initially developed by Twitter to enable consistent design across all Twitter tools. But now it’s the popular free CSS framework. Simply to understand the Bootstrap, let’s say you would like to add some styles in your web page. You are using HTML table in your web site and you want all tables to have same design/style all across the web site. In Bootstrap framework, you will find some CSS classes that you can use to have nice, impressive look for table all across the site. To apply default Bootstrap table style, just apply the CSS class “table”. If you would like to add hover style in the table add “table-hover” CSS in the the table class. Applying the following table styles results in the table shown in figure 1. The table has rounded corner, alternate color and nice/slick border width.</p> <div id="codeSnippetWrapper"> <pre id="codeSnippet" class="csharpcode"><span class="kwrd"><</span><span class="html">table</span> <span class="attr">class</span><span class="kwrd">="table table-bordered table-striped table-hover"</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">table</span><span class="kwrd">></span></pre>
<br /></div>
<p><a href="http://lh3.ggpht.com/-Zs_6losrV1M/UUU7UkTfROI/AAAAAAAAA_8/FclGVwi6mMY/s1600-h/image%25255B19%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-kaX_fff2zjg/UUU7YKhPbLI/AAAAAAAABAE/wIJsQjP4olQ/image_thumb%25255B9%25255D.png?imgmax=800" width="786" height="208" /></a> </p>
<p>Figure 1: Table with round corner and slick look with Bootstrap CSS styles </p>
<p> </p>
<p>You can check the default table styles provided by Bootstrap at this link: <a title="http://twitter.github.com/bootstrap/base-css.html#tables" href="http://twitter.github.com/bootstrap/base-css.html#tables">http://twitter.github.com/bootstrap/base-css.html#tables</a></p>
<p>While you will develop SharePoint Apps, you can easily integrate Bootstrap in your app and can get impressive look and feel.</p>
<p> </p>
<h4>How to integrate Bootstrap with SharePoint App</h4>
<p>To use the Bootstrap in your app, first download the Bootstrap from <a href="http://twitter.github.com/bootstrap/index.html" target="_blank">Twitter Github</a>. Once you extract the zip file, you will find three types of resources you need to use: CSS files, JavaScript Files and image files. </p>
<h5><strong>Step1: Copy the Bootstrap files in corresponding App folders (shown in Figure 2)</strong>:</h5>
<ul>
<li>Copy contents of the the the Bootstrap “css” folder to “content” folder in your app in Visual Studio. I would recommend you to copy min file(s) only. </li>
<li>Copy contents of the Bootstrap “img” folder to the Visual Studio “Images” folder. </li>
<li>Copy contents of the Bootstrap “js” folder to the Visual Studio “Scripts” folder. I would recommend  you to copy min file(s) only </li>
</ul>
<p><a href="http://lh6.ggpht.com/-ddyBLWY9Cco/UUU7gEME--I/AAAAAAAABAM/XhulyYnZJG4/s1600-h/image%25255B15%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-npRVAQJkfpU/UUU7kVNJXsI/AAAAAAAABAU/rf-j3WNKaj8/image_thumb%25255B7%25255D.png?imgmax=800" width="658" height="552" /></a> </p>
<p>Figure 2: Copy Bootstrap files in your Visual Studio App project</p>
<h5> </h5>
<h5>Step 2: Make Image/img folder related Changes</h5>
<p>Bootstrap uses two images files which defines icons. These image files supposed to copy in App “Img” folder, as Bootstrap looks for these images in “img” folder. But SharePoint image folder name “Images” whereas Bootstrap Images folder name is “img”. So we need to update Bootstrap CSS file. Open the file “<strong>bootstrap.min.css</strong>” in the Visual Studio from “Content” folder. Then find for “.png” using Ctrl + F, and finally modify the image path from “img” to “Images” as shown below. You need to make changes in few places in the file:</p>
<p><a href="http://lh4.ggpht.com/-Xhc_Cl2F7j8/UUU7lLjKxQI/AAAAAAAABAc/Fa1JGLDcx-Y/s1600-h/image%25255B11%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-hh4YK6ns2cY/UUU7lwoKGrI/AAAAAAAABAk/ZLzmyRGPzs0/image_thumb%25255B5%25255D.png?imgmax=800" width="789" height="390" /></a> </p>
<p>Figure 3: Update Image Reference in Bootstrap Css file.</p>
<p></p>
<p> </p>
<h5>Step 3: Add Reference to the Bootstrap files in your page</h5>
<p>The final step is to add reference to these Bootstrap reference in you page. Add the following references in your page in App under content place holder “PlaceHolderAdditionalPageHead” or any other suitable places:</p>
<div>
<pre id="codeSnippet" class="csharpcode"><span class="kwrd"><</span><span class="html">link</span> <span class="attr">rel</span><span class="kwrd">="Stylesheet"</span> <span class="attr">type</span><span class="kwrd">="text/css"</span> <span class="attr">href</span><span class="kwrd">="../Content/bootstrap-responsive.min.css"</span> <span class="kwrd">/></span><br /><span class="kwrd"><</span><span class="html">link</span> <span class="attr">rel</span><span class="kwrd">="Stylesheet"</span> <span class="attr">type</span><span class="kwrd">="text/css"</span> <span class="attr">href</span><span class="kwrd">="../Content/bootstrap.min.css"</span> <span class="kwrd">/></span><br /><br /><span class="kwrd"><</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span> <span class="attr">src</span><span class="kwrd">="../Scripts/bootstrap.min.js"</span><span class="kwrd">></</span><span class="html">script</span><span class="kwrd">></span></pre>
</div>
<div> </div>
<h4>Download Source Code</h4>
<p>I’ve created a sample SharePoint 2013 App project with the Bootstrap integrated. You can download the sample project <a href="http://sdrv.ms/YFa4gO" target="_blank">BootstrapTest from my Skydrive</a>.</p>
<div>
<br /></div>
<h4>Conclusion</h4>
<p>With the growing popularity of Bootstrap, we should  know about the framework and need to use it for appropriate applications. I’ve not tried Bootstrap with SharePoint webparts or full-trust applications but I’ll try to investigate in future. However, if you have not already tried <a href="http://twitter.github.com/bootstrap/index.html" target="_blank">Twitter Bootstrap</a> please give a try, I do believe you’ll like it!</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com6tag:blogger.com,1999:blog-1804865242850018128.post-31925764616708338702013-03-07T11:21:00.001+07:002013-03-07T11:21:47.576+07:00SharePoint 2013: Workflow Debug/Diagnosis<p>In SharePoint 2013, new workflow model introduced. Now the workflow runs in different servers (or farms) and SharePoint communicates to the workflow server via REST endpoints. This is really scalable and decoupled architecture but it brings new challenges for workflow developers. Now debugging is not so easy as it was before with SharePoint 2010 workflows. Still you can develop/debug SharePoint 2010 workflows in SharePoint 2013 but it’s not recommended anymore. I’ll explain the techniques you can use to debug your workflow. If the workflow fails to run you will find the workflow error like HTTP 500 or Internal server error. You need to find out by yourself what went wrong. Till date, Workflow doesn’t have inherent functionality to trace the requests though as per <a href="http://social.msdn.microsoft.com/Forums/en-US/wflmgr/thread/6383b826-4764-49f0-b807-0d157092b0f6" target="_blank">this forum post</a>, Workflow team is working on some tracing tools for next version.</p> <p>Now let me describe few external tools/techniques you can use to diagnosis your workflow.</p> <h4>Event Viewer</h4> <p>Windows Server running workflow service can trace workflow manager and service bus activities. By default the Analytic and debug log for workflow manager is disabled. You can enable the event viewer and see what’s going on under the hood. You can find out details on how to enable the event viewer in the link: <a title="http://technet.microsoft.com/en-us/library/jj193526" href="http://technet.microsoft.com/en-us/library/jj193526">http://technet.microsoft.com/en-us/library/jj193526</a></p> <p> </p> <h4>HTTP Traffic Tracing</h4> <p>You can use some HTTP packet traffic tracing tools in SharePoint Server and trace the request back and forth between SharePoint and Workflow server. One such nice tool (though not free) that I’ve found is <a href="http://www.httpdebugger.com/" target="_blank">HTTP Debugger</a>. However you can use any other tools that watch HTTP traffic at the network level (not browser level). So tools like Fiddler will not help as it just trace requests made from Browser whereas we need tools that trace HTTP traffic at network level.</p> <p> </p> <h4>Database Log</h4> <p>In the workflow Management database, there’s a table ‘DebugTraces’. I’ve noticed that sometimes Workflow Manager write down errors/debugs in this database tables. You can go and take a look if something is useful for your workflow debugging.</p> <p> </p> <h4>Conclusion</h4> <p>You can use all above tools in combination in finding out problem in different parts of the full workflow lifecycle. You can use HTTP Tracing tools to find out if the Workflow Service call from SharePoint goes to Workflow Manager or vice versa. Using event viewer or database log, you can find out if there’s any errors in your workflow during execution. Until some built-in tools are available for workflow tracing, you can use these tools to find out your problem relatively quickly.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-55149621878670645962013-02-28T15:25:00.002+07:002013-03-07T10:23:29.213+07:00Workflow Manager cumulative update (February) errorAfter installing workflow manager cumulative update in February 2013, the workflow manager stopped working. When I was trying to access workflow settings in the list/library I was getting unexpected exception. Then I found the following error in the log file: <br /> <h5><span style="color: red">The EXECUTE permission was denied on the object 'InsertTrackingAndStatus'</span></h5> <br />To fond out how to enable and view the workflow manager log file, please follow the technet guide at: <a href="http://technet.microsoft.com/en-us/library/jj193526.aspx">http://technet.microsoft.com/en-us/library/jj193526.aspx</a>. From the error message it seems the problem is related to database permission related. So connected to the database (using SQL management studio) and found out the workflow manager windows service user's (under whose credentila's the workflow service is running) security settings. The original permission I found was "WFServiceOperators" and then I added dbo permission to the user also.  Then I restarted the SQL service and it all started working. I know this is not the best solution but for time being the hack solved the problem in my Dev. <br /> <br /> <h4>Update From Workflow Team</h4> <p><span style="font-weight: normal">I've posted the bug in Workflow forum: <a href="http://social.msdn.microsoft.com/Forums/en-US/wflmgr/thread/054d2a58-8847-4a6a-b1ab-05a79f49fe65" target="_blank">http://social.msdn.microsoft.com/Forums/en-US/wflmgr/thread/054d2a58-8847-4a6a-b1ab-05a79f49fe65  </a>. As described in the forum, you need to run the following script against the database:</span> </p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">IF</span> <span style="color: #0000ff">EXISTS</span> (<span style="color: #0000ff">SELECT</span> * <span style="color: #0000ff">FROM</span> sys.database_principals <span style="color: #0000ff">WHERE</span> name = N<span style="color: #006080">'WFServiceOperators'</span> <span style="color: #0000ff">AND</span> type = <span style="color: #006080">'R'</span>)<br /><span style="color: #0000ff">BEGIN</span><br /> <span style="color: #008000">-- Grant all permissions of stored procedures and tables</span><br /> <span style="color: #0000ff">DECLARE</span> @ObjectName sysname, @ObjectType <span style="color: #0000ff">char</span>(20), @Cmd <span style="color: #0000ff">varchar</span>(300)<br /> <span style="color: #0000ff">DECLARE</span> ObjectCursor <span style="color: #0000ff">CURSOR</span> <span style="color: #0000ff">LOCAL</span> FAST_FORWARD<br /> <span style="color: #0000ff">FOR</span> <span style="color: #0000ff">SELECT</span> name, type <span style="color: #0000ff">FROM</span> sys.objects <span style="color: #0000ff">UNION</span> <span style="color: #0000ff">SELECT</span> name, <span style="color: #006080">'WFUDT'</span> <span style="color: #0000ff">FROM</span> sys.types <span style="color: #0000ff">WHERE</span> is_user_defined = 1<br /><br /> <span style="color: #0000ff">OPEN</span> ObjectCursor<br /> <span style="color: #0000ff">FETCH</span> ObjectCursor <span style="color: #0000ff">INTO</span> @ObjectName, @ObjectType<br /> <span style="color: #0000ff">WHILE</span> (@@fetch_status <> -1)<br /> <span style="color: #0000ff">BEGIN</span> <br /> <span style="color: #0000ff">SET</span> @Cmd =<br /> <span style="color: #0000ff">CASE</span> @ObjectType<br /> <span style="color: #0000ff">WHEN</span> <span style="color: #006080">'P'</span> <span style="color: #0000ff">THEN</span> N<span style="color: #006080">'GRANT EXECUTE ON ['</span> + @ObjectName + N<span style="color: #006080">'] TO [WFServiceOperators]'</span> <br /> <span style="color: #0000ff">WHEN</span> <span style="color: #006080">'WFUDT'</span> <span style="color: #0000ff">THEN</span> N<span style="color: #006080">'GRANT CONTROL, REFERENCES ON TYPE::['</span> + @ObjectName + N<span style="color: #006080">'] TO [WFServiceOperators]'</span> <br /> <span style="color: #0000ff">ELSE</span> <span style="color: #006080">''</span><br /> <span style="color: #0000ff">END</span><br /><br /> <span style="color: #0000ff">IF</span> @Cmd <> <span style="color: #006080">''</span><br /> <span style="color: #0000ff">BEGIN</span><br /> <span style="color: #0000ff">EXEC</span>(@Cmd)<br /> <span style="color: #0000ff">END</span><br /> <span style="color: #0000ff">FETCH</span> ObjectCursor <span style="color: #0000ff">INTO</span> @ObjectName, @ObjectType<br /> <span style="color: #0000ff">END</span><br /> <span style="color: #0000ff">CLOSE</span> ObjectCursor<br /> <span style="color: #0000ff">DEALLOCATE</span> ObjectCursor<br /><span style="color: #0000ff">END</span><br /><span style="color: #0000ff">GO</span><br /> </pre>
<br /></div>
<p>
<br />
<br /><span style="font-weight: normal">But still if the above script doesn't solve your problem, you can set the workflow user as dbo in the database</span></p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com1tag:blogger.com,1999:blog-1804865242850018128.post-90385356454490117912013-02-17T10:58:00.001+07:002013-04-14T11:27:50.485+07:00SharePoint 2013: Workflow Manager Installation and Configuration<p>SharePoint 2013 introduced a new way of workflow management. Now workflow can be hosted in separate server – so scalable and reduces load on SharePoint Web Front End server. However this introduce a new level of complexity that we need to be aware of. </p> <h4> </h4> <h4>Introduction</h4> <p>To use a windows server as workflow manager you need to install/configure Workflow Manager in the windows server. Workflow manager is a new kind of application server that host/manage workflow execution. SharePoint 2013 workflow is based on .net framework 4.0. Workflow Manager is designed with Window Azure hosting in mind, but now it supports on-premise installation. If organizations now want to host the workflow on-premise they can still use Workflow Manager but in future if they want to move to Windows Azure hosting for their workflow, the migration will be smoother with this Workflow Manager.</p> <h4> </h4> <h4>You should Know</h4> <p>Before start installing/developing SharePoint Manager you need to know few points:</p> <ul> <li>You should not use SharePoint ‘system account’ to test workflow. If you use ‘system account’ to develop/run workflow, the workflow will fail to run. </li> <li>You need to make sure User Profile Service (UPS) is running and the user who is running workflow has profile in UPS. Workflow Manager use UPS under the hood. </li> <li>Make sure App Management Service is created and running. You don’t need to configure SharePoint 2013 App settings in the server, just creating App Management service (with proxy) will do. </li> <li>SharePoint 2013 workflow is declarative – means you can only define workflow in XML. You can’t write any C# code inside workflow as you used to do before. All your custom logic should be put outside of SharePoint, inside WCF Service. Then you will call the service from workflow to implement your custom logic in code. </li> <li>To register workflow Server with SharePoint, a SharePoint site collection URL is provided (see the section <strong>Register Workflow Service with SharePoint </strong>later in the post). Apparently it seems, each and every site collection need to be registered with workflow server. But it’s not, registering a single SharePoint site  collection, will enable workflow manager for all SharePoint web applications/site collections. </li> </ul> <p> </p> <h4>Install/Configure Workflow Manager</h4> <p>The first step in workflow setup/configuration is to install workflow manager in the workflow server (either Web Front End or a separate server). To install the workflow Manager download it from <a href="http://www.microsoft.com/en-us/download/details.aspx?id=35375" target="_blank">Microsoft Site</a> or alternatively you can download it from Web Platform Installer. The installation contains few components:</p> <ul> <li>Workflow Manager: This is the host that runs workflows. </li> <li>Workflow Manager Client: It contains the API to allow clients to communicate with Workflow host. </li> <li>Workflow Tool: It needs to be installed in the development server to develop SharePoint 2013 workflow. It supports the workflow development in Visual Studio 2012. </li> </ul> <p>Workflow Manager client needs to be installed in every SharePoint WFE server.</p> <p>After installing Workflow Manger, you can configure workflow manager with Workflow Manager Configuration Wizard. The configuration involves two steps: Workflow Manager Configuration and Service Bus Configuration. </p> <ul> <li>Workflow Manger Configuration (first step in the wizard) is the configuration related to work host server </li> <li>Service Bus configuration (second step in the wizard): Service Bus is used to manage communication between Workflow Server and it’s client (so, SharePoint). Service Bus queues the income request to workflow manage, provide REST interface for Workflow Manager etc. </li> </ul> <p>In workflow configuration wizard don’t use any admin or SharePoint setup user, create a new service user for workflow and use that user:</p> <p><a href="http://lh4.ggpht.com/-zYInVIGfYvQ/USBVRw3QyBI/AAAAAAAAA-A/ctVNck_3wXI/s1600-h/image%25255B3%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-NfGvIWNQvCA/USBVSljb8YI/AAAAAAAAA-I/PTv1IpJKQMA/image_thumb%25255B1%25255D.png?imgmax=800" width="696" height="519" /></a> </p> <p><strong>Figure 1: Workflow Manager Service Account</strong></p> <p><strong></strong></p> <p> </p> <p>If you want SharePoint Server to communicate with Workflow Server over HTTP, you can select the option shown below. But please make sure this is secure in your case. For public site, this might not be secure but in case of Local Intranet with firewall, this might be secure.</p> <p><a href="http://lh5.ggpht.com/-_2pR0MT66Vg/USBVZBLAunI/AAAAAAAAA-Q/QdBdZvo26nE/s1600-h/image%25255B7%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-kVUqEczd-m0/USBVaAobFWI/AAAAAAAAA-Y/kwJh627wglI/image_thumb%25255B3%25255D.png?imgmax=800" width="468" height="466" /></a> </p> <p><strong>Figure 2: Communication over HTTP</strong></p> <p><strong></strong></p> <p> </p> <p>If you want to use the same service account (as well as auto generated key for certificate), you can use so as shown below:</p> <p><a href="http://lh4.ggpht.com/-KAUKvZgs-io/USBVbDc_akI/AAAAAAAAA-g/gm2e0tNf21k/s1600-h/image%25255B11%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-Jko4DcD-4Vg/USBVb_p-wuI/AAAAAAAAA-o/AXvySzKAq8s/image_thumb%25255B5%25255D.png?imgmax=800" width="641" height="410" /></a> </p> <p><strong>Figure 3: Same service account and certificate key is used for both Workflow Manager and Service Bus Configuration.</strong> </p> <p>In the final step of the workflow configuration wizard you can generate PowerShell script that you can reuse across different SharePoint Farms.</p> <p> </p> <h4>Register Workflow Service with SharePoint</h4> <p>Once you have installed/configured Workflow Server, you need to register the workflow service to SharePoint Server. The registration depends on how the SharePoint and Workflow server is connected to each other. You can find more details at <a href="http://technet.microsoft.com/en-us/library/jj658588(v=office.15)#section5" target="_blank">technet site</a>. The workflow manager creates an HTTPS endpoint at port 12291 and HTTP port at 12290. If you use HTTP for communication you need to provide ‘AllowOAuthHttp’ switch in the PowerShell command. The PowerShell command looks like below:</p> <p><strong>Communication over HTTP</strong></p> <p>Register-SPWorkflowService –SPSite <a href="http://sharepointsite">http://sharepointsite</a> –WorkflowHostUri <a href="http://workflowhost:12291">http://workflowhost:12291</a> –AllowOAuthHttp</p> <p> </p> <p><strong>Communication over HTTPS</strong></p> <p>Register-SPWorkflowService –SPSite <a href="http://sharepointsite">http://sharepointsite</a> –WorkflowHostUri <a href="https://workflowhost:12290">https://workflowhost:12290</a></p> <p> </p> <h4>PowerShell Script to Install/Configure Workflow Manager</h4> <p>I have modified the wizard-generated PowerShell script a bit to make it more reusable. The Script reads configuration values from xml file and apply the configuration. The script uses auto-generate key for certificate. Also the database name are hard-coded in the script, but you can add prefixes (like dev, test, prod) to the database from xml file. The script also configure App Management Service, if the service is not already created. The sample PowerShell Script is provided below:</p> <div id="codeSnippetWrapper"> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 96.48%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; height: 650px; max-height: 700px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">#Get current user full login name</span><br />$CurrentUserLoginName=[Environment]::UserName + <span style="color: #006080">'@'</span> + [Environment]::UserDomainName;<br /><span style="color: #008000">#Get current server fully qualified domain name</span><br />$HostFQDN=<span style="color: #006080">"$env:computername.$env:userdnsdomain"</span>;<br /><br /><span style="color: #008000">#Load SharePoint Snapin</span><br /><span style="color: #0000ff">if</span> ( (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) <span style="color: #cc6633">-eq</span> $null ){ <br /> Add-PsSnapin Microsoft.SharePoint.PowerShell<br />}<br /><br /><span style="color: #008000">#Get DB Connection String</span><br /><span style="color: #0000ff">function</span> GetDBConnectionString([string]$connectionStringFormat, [string]$dbPrefix, [string]$dbName){<br /> <span style="color: #0000ff">if</span>($dbPrefix <span style="color: #cc6633">-ne</span> <span style="color: #006080">""</span>){<br /> $dbFullName=$(GetDBName $dbPrefix $dbName);<br /> <span style="color: #0000ff">return</span> [string]::Format($connectionStringFormat,$dbFullName);<br /> }<br /> <span style="color: #0000ff">else</span> {<br /> <span style="color: #0000ff">return</span> $dbName;<br /> }<br />}<br /><br /><span style="color: #008000">#Add Dev, Test etc. environment prefix, if needed</span><br /><span style="color: #0000ff">function</span> GetDBName([string]$dbPrefix,[string]$dbName){<br /> <span style="color: #0000ff">if</span>(($dbPrefix) -and ($dbPrefix <span style="color: #cc6633">-ne</span> <span style="color: #006080">""</span>)){<br /> <span style="color: #0000ff">return</span> $dbPrefix + <span style="color: #006080">"_"</span> + $dbName;<br /> }<br /> <span style="color: #0000ff">return</span> $dbName;<br />}<br /><br /><span style="color: #008000">#Get current Script directory</span><br /><span style="color: #0000ff">function</span> Get-ScriptDirectory<br />{<br /> $Invocation = (Get-Variable MyInvocation -Scope 1).Value<br /> Split-Path $Invocation.MyCommand.Path<br />}<br /><br /><span style="color: #0000ff">function</span> ConfigureWFManager([string]$settingsFile){<br /> [xml]$wfsettings = Get-Content $settingsFile<br /> $settings=$wfsettings.Settings;<br /> $SharePointSiteUrl=$settings.SiteUrl;<br /> $dbPrefix=$settings.DBPrefix;<br /> $CertificateKey=$settings.CertificationKey;<br /> $databaseServer=$settings.DBServer;<br /> $ConnectionStringFormat=<span style="color: #006080">"Data Source=$databaseServer;Initial Catalog={0};Integrated Security=True;Encrypt=False"</span>;<br /> $RunAsAccount=$settings.WFManagerRunAsUser;<br /> $RunAsPasswordPlain=$settings.WFManagerRunAsPassword<br /> $WorkflowNamespace=$settings.WorkflowNamespace;<br /> <span style="color: #0000ff">if</span>(ShouldIProvision($settings.AppManagementService))<br /> {<br /> ProvisionAppManagementService($settings);<br /> }<br /><br /> <span style="color: #008000"># To be run in Workflow Manager PowerShell console that has both Workflow Manager and Service Bus installed.</span><br /> <span style="color: #008000"># Create new Service Bus Farm</span><br /> $SBCertificateAutoGenerationKey = ConvertTo-SecureString -AsPlainText -Force -String $CertificateKey -Verbose;<br /><br /> New-SBFarm -SBFarmDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'SBManagementDB'</span>) -InternalPortRangeStart 9000 -TcpPort 9354 -MessageBrokerPort 9356 -RunAsAccount $RunAsAccount -AdminGroup <span style="color: #006080">'BUILTIN\Administrators'</span> -GatewayDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'SBGatewayDB'</span>) -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey -MessageContainerDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'SBMessageContainerDB'</span>) -Verbose;<br /><br /> <span style="color: #008000"># To be run in Workflow Manager PowerShell console that has both Workflow Manager and Service Bus installed.</span><br /><br /> <span style="color: #008000"># Create new Workflow Farm</span><br /> $WFCertAutoGenerationKey = ConvertTo-SecureString -AsPlainText -Force -String $CertificateKey -Verbose;<br /><br /><br /> New-WFFarm -WFFarmDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'WFManagementDB'</span>) -RunAsAccount $RunAsAccount -AdminGroup <span style="color: #006080">'BUILTIN\Administrators'</span> -HttpsPort 12290 -HttpPort 12291 -InstanceDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'WFInstanceManagementDB'</span>) -ResourceDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'WFResourceManagementDB'</span>) -CertificateAutoGenerationKey $WFCertAutoGenerationKey -Verbose;<br /><br /> <span style="color: #008000"># Add Service Bus Host</span><br /> $SBRunAsPassword = ConvertTo-SecureString -AsPlainText -Force -String $RunAsPasswordPlain -Verbose;<br /><br /><br /> Add-SBHost -SBFarmDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'SBManagementDB'</span>) -RunAsPassword $SBRunAsPassword -EnableFirewallRules $true -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey -Verbose;<br /><br /> Try<br /> {<br /> <span style="color: #008000"># Create new Servie Bus Namespace</span><br /> New-SBNamespace -Name $WorkflowNamespace -AddressingScheme <span style="color: #006080">'Path'</span> -ManageUsers $RunAsAccount,$CurrentUserLoginName -Verbose;<br /><br /> Start-Sleep -s 90<br /> }<br /> Catch [system.InvalidOperationException]<br /> {<br /> }<br /><br /> <span style="color: #008000"># Get Service Bus Client Configuration</span><br /> $SBClientConfiguration = Get-SBClientConfiguration -Namespaces $WorkflowNamespace -Verbose;<br /><br /> <span style="color: #008000"># Add Workflow Host</span><br /> $WFRunAsPassword = ConvertTo-SecureString -AsPlainText -Force -String $RunAsPasswordPlain -Verbose;<br /><br /><br /> Add-WFHost -WFFarmDBConnectionString $(GetDBConnectionString $connectionStringFormat $dbPrefix <span style="color: #006080">'WFManagementDB'</span>) -RunAsPassword $WFRunAsPassword -EnableFirewallRules $true -SBClientConfiguration $SBClientConfiguration -EnableHttpPort -CertificateAutoGenerationKey $WFCertAutoGenerationKey -Verbose;<br /><br /> Write-Host <span style="color: #006080">"Registering workflow host (HTTP) to site: $SharePointSiteUrl"</span>;<br /> Register-SPWorkflowService –SPSite $SharePointSiteUrl –WorkflowHostUri $(<span style="color: #006080">"http://$HostFQDN"</span> + <span style="color: #006080">":12291"</span>) –AllowOAuthHttp<br />}<br /><br /><span style="color: #0000ff">function</span> ProvisionAppManagementService([System.Xml.XmlNode] $settings){<br /><br /> $appManagementServices=Get-SPServiceApplication | Where-Object { $_.GetType().ToString() <span style="color: #cc6633">-eq</span> <span style="color: #006080">"Microsoft.SharePoint.AppManagement.AppManagementServiceApplication"</span>}<br /> If($appManagementServices <span style="color: #cc6633">-ne</span> $null)<br /> {<br /> Write-Host <span style="color: #006080">"An App Managemetn service is already running. Returning.."</span> -ForegroundColor Yellow<br /> <span style="color: #0000ff">return</span>;<br /> } <br /> <br /> Write-Host <span style="color: #006080">"Provisioning App Management Service"</span>;<br /> $appManagementService=$settings.AppManagementService;<br /> $appPool=$(GetAppPool $appManagementService)<br /> $dbName=$(GetDBName $settings.DBPrefix $appManagementService.DBName);<br /> $appAppSvc = New-SPAppManagementServiceApplication -ApplicationPool $appPool -Name $appManagementService.Name -DatabaseName $dbName<br /> New-SPAppManagementServiceApplicationProxy -ServiceApplication $appAppSvc<br />}<br /><br /><span style="color: #0000ff">function</span> GetAppPool([System.Xml.XmlNode] $appManagementService){<br /> $pool = Get-SPServiceApplicationPool -Identity $AppManagementService.AppPoolName -ErrorVariable err -ErrorAction SilentlyContinue<br /> If ($err) {<br /> <span style="color: #008000"># The application pool does not exist so create.</span><br /> Write-Host -ForegroundColor White <span style="color: #006080">" - Getting $($appManagementService.ManagedAccountUserName) account for application pool..."</span><br /> $managedAccount = (Get-SPManagedAccount -Identity $appManagementService.ManagedAccountUserName -ErrorVariable err -ErrorAction SilentlyContinue)<br /> If ($err) {<br /> If (($appManagementService.ManagedAccountPassword <span style="color: #cc6633">-ne</span> <span style="color: #006080">""</span>) -and ($appManagementService.ManagedAccountPassword <span style="color: #cc6633">-ne</span> $null)) <br /> {<br /> $appPoolConfigPWD = (ConvertTo-SecureString $appManagementService.ManagedAccountPassword -AsPlainText -force)<br /> $accountCred = New-Object System.Management.Automation.PsCredential $appManagementService.ManagedAccountUserName,$appPoolConfigPWD<br /> }<br /> Else<br /> {<br /> $accountCred = Get-Credential $appManagementService.ManagedAccountUserName<br /> }<br /> $managedAccount = New-SPManagedAccount -Credential $accountCred<br /> }<br /> Write-Host -ForegroundColor White <span style="color: #006080">" - Creating applicatoin pool $($appManagementService.AppPoolName)..."</span><br /> $pool = New-SPServiceApplicationPool -Name $appManagementService.AppPoolName -Account $managedAccount<br /> }<br /> <span style="color: #0000ff">return</span> $pool;<br />}<br /><br />Function ShouldIProvision([System.Xml.XmlNode] $node)<br />{<br /> If (!$node) {Return $false} <span style="color: #008000"># In case the node doesn't exist in the XML file</span><br /> <span style="color: #008000"># Allow for comma- or space-delimited list of server names in Provision or Start attribute</span><br /> If ($node.GetAttribute(<span style="color: #006080">"Provision"</span>)) {$v = $node.GetAttribute(<span style="color: #006080">"Provision"</span>).Replace(<span style="color: #006080">","</span>,<span style="color: #006080">" "</span>)}<br /> ElseIf ($node.GetAttribute(<span style="color: #006080">"Start"</span>)) {$v = $node.GetAttribute(<span style="color: #006080">"Start"</span>).Replace(<span style="color: #006080">","</span>,<span style="color: #006080">" "</span>)}<br /> ElseIf ($node.GetAttribute(<span style="color: #006080">"Install"</span>)) {$v = $node.GetAttribute(<span style="color: #006080">"Install"</span>).Replace(<span style="color: #006080">","</span>,<span style="color: #006080">" "</span>)}<br /> If ($v <span style="color: #cc6633">-eq</span> $true) { Return $true; }<br /> Return $false;<br />}<br /><br />Write-Host <span style="color: #006080">"Configuring WF Manager"</span><br />$location=Get-ScriptDirectory<br />ConfigureWFManager <span style="color: #006080">"$location\WFFarmSettings.xml"</span></pre>
<br /></div>
<br /></div>
<p><strong>Code Snippet: PowerShell Script to configure Workflow Manager</strong></p>
<p><strong></strong></p>
<p>The following XML file provides the input settings for the above PowerShell script (named as WFFarmSettings.xml in the above PowerShell script). Though you will use a site collection to register the workflow and SharePoint communication, I’ve found that workflow work for all others site collections/web application in the SharePoint Server.</p>
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">Settings</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">SiteUrl</span><span class="kwrd">></span>http://siteulr<span class="kwrd"></</span><span class="html">SiteUrl</span><span class="kwrd">></span>
<span class="rem"><!--Delete DBPrefix tag, if you don't want any prefix--></span>
<span class="kwrd"><</span><span class="html">DBPrefix</span><span class="kwrd">></span>DEV<span class="kwrd"></</span><span class="html">DBPrefix</span><span class="kwrd">></span>
<span class="rem"><!--Key used to generate certificates--></span>
<span class="kwrd"><</span><span class="html">CertificationKey</span><span class="kwrd">></span>CertificationKey<span class="kwrd"></</span><span class="html">CertificationKey</span><span class="kwrd">></span>
<span class="rem"><!--Database server name, database names are hardcoded in powershell--></span>
<span class="kwrd"><</span><span class="html">DBServer</span><span class="kwrd">></span>DBServer<span class="kwrd"></</span><span class="html">DBServer</span><span class="kwrd">></span>
<span class="rem"><!--Format should be USERNAME@DOMAIN--></span>
<span class="kwrd"><</span><span class="html">WFManagerRunAsUser</span><span class="kwrd">></span>user@domain<span class="kwrd"></</span><span class="html">WFManagerRunAsUser</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">WFManagerRunAsPassword</span><span class="kwrd">></span>Password<span class="kwrd"></</span><span class="html">WFManagerRunAsPassword</span><span class="kwrd">></span>
<span class="rem"><!--dot (.) not allowed--></span>
<span class="kwrd"><</span><span class="html">WorkflowNamespace</span><span class="kwrd">></span>WorkflowNamespace<span class="kwrd"></</span><span class="html">WorkflowNamespace</span><span class="kwrd">></span>
<span class="rem"><!--To work with workflow, app management service need to be provisioned--></span>
<span class="kwrd"><</span><span class="html">AppManagementService</span> <span class="attr">Provision</span><span class="kwrd">="true"</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Name</span><span class="kwrd">></span>App Management Service Application<span class="kwrd"></</span><span class="html">Name</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">DBName</span><span class="kwrd">></span>AppManagementServiceDB<span class="kwrd"></</span><span class="html">DBName</span><span class="kwrd">></span>
<span class="rem"><!--If managed account already exists with the same name, the existing one will be used--></span>
<span class="kwrd"><</span><span class="html">ManagedAccountUserName</span><span class="kwrd">></span><span class="kwrd"></</span><span class="html">ManagedAccountUserName</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">ManagedAccountPassword</span><span class="kwrd">></span><span class="kwrd"></</span><span class="html">ManagedAccountPassword</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">AppPoolName</span><span class="kwrd">></span>App Management Service App Pool<span class="kwrd"></</span><span class="html">AppPoolName</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">AppManagementService</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">Settings</span><span class="kwrd">></span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com40tag:blogger.com,1999:blog-1804865242850018128.post-670912891787337062012-12-02T20:35:00.000+07:002012-12-02T20:36:49.174+07:00SharePoint 2013: Use CAML into REST request<p>You might wonder how to use CAML query in your SharePoint 2013 REST endpoints. Basically you can’t pass CAML into REST request (at least till date, there’s so documented approach published). However, REST by itself provides the querying feature which somehow covers almost all CAML querying features. I’ll try to explain today how you can convert your CAML into REST request.</p> <h4>Generate REST Request Url</h4> <p>First of all let’s play with a tool called <a href="http://www.linqpad.net/" target="_blank">LINQPad</a> that will be used for REST request generation later from CAML.Let’s describe the process step by step.</p> <ol> <li><strong>Download LINQPad</strong>: The tool that I’m going to use for generating REST request url can be downloaded from <a href="http://www.linqpad.net/" target="_blank">LINQPad site</a>. So please download the tool and run it. </li> <li><strong>Add Connection Provider</strong>: Once you run the tool click ‘Add Connection’ and then select ‘WCF Data Services (OData)’ data context provider as shown below: <br /><a href="http://lh6.ggpht.com/-d_LbTjhOiU4/ULtZPxwLwKI/AAAAAAAAA7Y/1KsS0oUA658/s1600-h/image3.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-iawY3Joef3o/ULtZQqYOuPI/AAAAAAAAA7g/_QGIfnvIrKk/image_thumb1.png?imgmax=800" width="763" height="522" /></a> <br />Figure 1: Add WCF Data Connection <br /></li> <li><strong>Connect to SharePoint Server</strong>: In the connection page, select the url as <a href="http://server/_vti_bin/ListData.svc">http://server/_vti_bin/ListData.svc</a> as shown below: <br /><a href="http://lh5.ggpht.com/-HlqJh4cDs7Y/ULtZRc6s8xI/AAAAAAAAA7k/V3zLlv7EF-Y/s1600-h/image7.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-F2WUQ6O9hfo/ULtZSVYbm7I/AAAAAAAAA7s/2Td6Y3hY15I/image_thumb3.png?imgmax=800" width="478" height="231" /></a> <br />Figure 2: ListData WCF Connection <br /></li> <li><strong>Built-in Query Option</strong>: Use built-in template for querying as shown below. Right click on your list/library and use any built-in template you want. <br /><a href="http://lh6.ggpht.com/-JZfdVuDNAYw/ULtZTg2UReI/AAAAAAAAA74/IjTBY9B6ss0/s1600-h/image11.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-k-oE_UhMX_U/ULtZVLj0G3I/AAAAAAAAA8A/MX0EPXWZLpA/image_thumb5.png?imgmax=800" width="483" height="628" /></a> <br />Figure 3: Use built-in template for generating query <br /></li> <li><strong>Generate Query</strong>: Once you finish the query, execute it and click the ‘Request Log’ button to see the REST request generated as shown below: <br /> <a href="http://lh4.ggpht.com/-xsNT631P5zE/ULtZWDDYm6I/AAAAAAAAA8I/rJyMYCXwsrI/s1600-h/image19.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-4GsZn-eVQao/ULtZXiumWOI/AAAAAAAAA8Q/u8cBaM9mHPo/image_thumb9.png?imgmax=800" width="533" height="440" /></a> <br />Figure 4: C# query and REST request <br /></li> </ol> <p>For details REST operator you can use for SharePoint 2013 REST endpoint can be found at <a href="http://msdn.microsoft.com/en-us/library/fp142385.aspx" target="_blank">MSDN link</a> under “Table 3. OData query operators”. For licensed version, LINQPad provides intellisense which really exciting feature.</p> <p> </p> <h4>Examples of C# query and corresponding REST URL</h4> <p>I’ve provided few basic examples of using the LINQPad tool to generate queries. For this example, let’s consider we have a product list with the following fields:</p> <p><a href="http://lh3.ggpht.com/-EJIvQ3VdBBI/ULtZYmr5-_I/AAAAAAAAA8U/ZIq-Lfaww9U/s1600-h/image23.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-fykbhfkBGQk/ULtZZX2iF9I/AAAAAAAAA8g/vh2q5WYn7KI/image_thumb11.png?imgmax=800" width="458" height="235" /></a> </p> <p>Figure 5: Sample product list</p> <p>The following examples explains the C# query and it’s corresponding REST Url:</p> <ul> <li><strong>Select all products whose name contains ‘sharepoint’</strong> <table border="1" cellspacing="0" cellpadding="2" width="770"><tbody> <tr> <td valign="top" width="104"><strong>C# Qeury</strong></td> <td valign="top" width="664"> <pre class="csharpcode">Product.Where (p => p.ProductName.ToLower().IndexOf(<span class="str">"sharepoint"</span>)!=-1)</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></td>
</tr>
<tr>
<td valign="top" width="104"><strong>ListData Url</strong></td>
<td valign="top" width="664"><a href="http://server/_vti_bin/ListData.svc/Product()?">http://server/_vti_bin/ListData.svc/Product()?</a>$filter=indexof(tolower(ProductName),'sharepoint') ne –1</td>
</tr>
<tr>
<td valign="top" width="104"><strong>REST URL</strong></td>
<td valign="top" width="664"><a href="http://server/_api/web/lists/getbytitle(‘Product’)?">http://server/_api/web/lists/getbytitle(‘Product’)?</a>$filter=indexof(tolower(ProductName),'sharepoint') ne –1</td>
</tr>
</tbody></table>
So the summary is that the filter is “<font color="#ff0000"><strong>$filter=indexof(tolower(ProductName),'sharepoint') ne –1</strong></font>”
<br /></li>
</ul>
<ul>
<li><strong><u>Select all products created on 10-Oct-2012 </u></strong>
<table border="1" cellspacing="0" cellpadding="2" width="770"><tbody>
<tr>
<td valign="top" width="104"><strong>C# Qeury</strong></td>
<td valign="top" width="664">
<pre class="csharpcode">Product.Where (p => p.Created.Value.Day==10 & p.Created.Value.Month==10 & p.Created.Value.Year==2012) </pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></td>
</tr>
<tr>
<td valign="top" width="104"><strong>ListData Url</strong></td>
<td valign="top" width="664"><a href="http://server/_vti_bin/ListData.svc/Product()?">http://server/_vti_bin/ListData.svc/Product()?</a>$filter=((day(Created) eq 10) and (month(Created) eq 10)) and (year(Created) eq 2012) </td>
</tr>
<tr>
<td valign="top" width="104"><strong>REST URL</strong></td>
<td valign="top" width="664"><a href="http://server/_api/web/lists/getbytitle(‘Product)?">http://server/_api/web/lists/getbytitle(‘Product’)?</a>$filter=((day(Created) eq 10) and (month(Created) eq 10)) and (year(Created) eq 2012) </td>
</tr>
</tbody></table>
<ul></ul>
So the filter is “<font color="#ff0000"><strong>$filter=((day(Created) eq 10) and (month(Created) eq 10)) and (year(Created) eq 2012)</strong></font>”
<br /></li>
</ul>
<p>As shown above two examples, you can find out more by yourself by using the LinqPad and the <a href="http://msdn.microsoft.com/en-us/library/fp142385.aspx" target="_blank">MSDN function references</a>.</p>
<h4> </h4>
<h4>Convert CAML to REST Url</h4>
<p>Now let’s consider you have an CAML XML as shown below which returns all items from a list whose title contains ‘sharepoint’ and takes first 10 items.</p>
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">Where</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">Contains</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">FieldRef</span> <span class="attr">Name</span><span class="kwrd">='Title'</span> <span class="kwrd">/></span>
<span class="kwrd"><</span><span class="html">Value</span> <span class="attr">Type</span><span class="kwrd">='Text'</span><span class="kwrd">></span>sharepoint<span class="kwrd"></</span><span class="html">Value</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">Contains</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">Where</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">QueryOptions</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">RowLimit</span><span class="kwrd">></span>10<span class="kwrd"></</span><span class="html">RowLimit</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">QueryOptions</span><span class="kwrd">></span></pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Now using LINQPad, we can convert the CAML to REST url as described below:</p>
<p><a href="http://lh5.ggpht.com/-uBb0F6rL6C4/ULtZafSsjgI/AAAAAAAAA8o/HHy6286TsvI/s1600-h/image%25255B8%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-goyA6MNYMW0/ULtZbsf8ocI/AAAAAAAAA8w/Z6mZE2Gy7QY/image_thumb%25255B3%25255D.png?imgmax=800" width="816" height="179" /></a> </p>
<p><strong>So the final REST Url will be </strong><a href="http://server/_vti_bin/ListData.svc/Product()?">http://server/_vti_bin/ListData.svc/Product()?</a>$filter=indexof(tolower(ProductName),'sharepoint') ne -1&$top=10</p>
<h4> </h4>
<h4>Conclusion</h4>
<p>Using a combination of LINQPad, OData query operators at <a href="http://msdn.microsoft.com/en-us/library/fp142385.aspx" target="_blank">MSDN link</a> and CAML query at your hand, you can generate proper REST URL to be used. So if you have a CAML query at your hand, with a little time investment you can generate corresponding REST URL with filters and select parameters.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-39820658208981720002012-11-27T04:15:00.000+07:002012-11-27T04:17:17.166+07:00SharePoint 2013: Debug your SharePoint App<p>In SharePoint 2013 app development, you need to run the app from visual studio to debug. However as you debug and you need to make some changes in html or JavaScript, you might wonder that you need to stop debugging, make changes and redeploy the app again. But there’s simplest solution exists.</p> <h4>Unproductive Approach</h4> <p>You might be aware of the following steps which might take long time to debug and make changes:</p> <ol> <li>Run the app from Visual Studio in debug mode (with F5). </li> <li>Debug your JavaScript and you’ve found you need to make changes </li> <li>Stop the debug and make changes </li> <li>Rerun the app from Visual Studio with F5 </li> </ol> <p>But there’s simplest approach exists for debugging as described next.</p> <p> </p> <h4>Productive Approach</h4> <p>You may not know that you don’t need to stop debugging to make changes. You can make changes while the app is running and then refresh the page in the browser. You will get your changes on refreshing/reloading the page. So the new steps are:</p> <ol> <li>Run the app from Visual Studio in debug mode (with F5). </li> <li>Debug your javascript and you’ve found you need to make changes </li> <li>Make those changes in Visual Studio without stopping the app. </li> <li>Refresh the page in Browser, you will get the changes (HTML, JavaScript) immediately. </li> </ol> <p> </p> <h4>Conclusion</h4> <p>Using the second (productive approach) approach, you can develop and debug faster. However, if you make any setting changes like feature changes or appmanifest changes, you need to stop debugging and rerun again.</p> Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0tag:blogger.com,1999:blog-1804865242850018128.post-73889946080913085402012-10-28T20:22:00.000+07:002012-10-28T20:22:36.159+07:00SharePoint 2013: Start Developing AppsSharePoint 2013 introduced new concept of ‘SharePoint apps’. Apart from Server Object Model, you can now user Client Object Model or REST API to develop SharePoint Apps. For developing apps, you don’t need to install SharePoint in your development pc. You can develop SharePoint apps in client Operating System like Windows 7or Windows 8. If you have not already started developing apps for SharePoint, this post might help you in getting started. To develop apps you need combination of two setups. <br /> <ul> <li><b>Development Environment</b>: where you install visual studio for developing apps. For your information for developing SharePoint apps you don’t need a SharePoint server. You can develop apps in your windows 7/8 environment. </li> <li><b>Deployment Environment</b>: where you can run your apps for testing/debugging. Surely this will be a SharePoint system.</li> </ul> <br />Based on the development and deployment environment integration, there are two ways you can setup your apps development environment: <br /> <h5><u>On-Premises Development Environment</u></h5> <p>In this setup, you install the development and deployment in the same server. This is kind of manual process of setting up your SharePoint server to work as apps hosting server. I would not like to recommend you for this setup unless you have a specific reason. You can find more details on how to setup your on-premises development environment by following the MSDN link on ‘<a href="http://msdn.microsoft.com/en-us/library/fp179923(v=office.15).aspx" target="_blank">How to: Set up an on-premises development environment for apps for SharePoint</a>’. The concept is shown below: <br /><a href="http://lh4.ggpht.com/-HskDoU_Xwxk/UI0pXADaMqI/AAAAAAAAA40/jgt8bYpF92Y/s1600-h/image%25255B15%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-tdqy1Z-4aTE/UI0pYIjl6uI/AAAAAAAAA48/gTJJlU7EXvg/image_thumb%25255B7%25255D.png?imgmax=800" width="468" height="142" /></a> <br /><b>Figure 1: On-Premises setup</b> <br /><b></b> <br /><b></b>Basically in he on-premises setup, you develop your own SharePoint server and then prepare it for publishing hub for SharePoint apps. You will develop apps in your development pc and then deploy in the on-premises SharePoint server.</p> <p> </p> <h5><u>Office 365 based development Environment</u></h5> In this setup the development environment is on-premises but the deployment environment is office 365. You can get your own deployment environment by signing up for office 365 developer site. You can find details on how to sign up for office 365 developer site from MSDN ‘<a href="http://msdn.microsoft.com/en-us/library/fp179924(v=office.15).aspx" target="_blank">Sign Up for an Office 365 Developer Site</a>’. The concept of this environment is shown below: <br /> <blockquote> <p> <a href="http://lh6.ggpht.com/-F3yclws3KWw/UI0pZEmsZ7I/AAAAAAAAA5E/Xo8FSBkyWxk/s1600-h/image%25255B42%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-GEKZUe8332Y/UI0pai6X8CI/AAAAAAAAA5M/8bBPYQ3D80k/image_thumb%25255B20%25255D.png?imgmax=800" width="500" height="166" /></a> <br /><b>Figure 2: Office 365 developer setup</b></p> </blockquote> <p>In the Office 365 development environment setup, you will develop in your own pc and then deploy in Office 365 developer site to test/debug. Once you are done with your development and want to publish it, you can do so by publishing in the office app market.</p> <p> </p> <b></b> <br /> <h4>Step by Step Instructions on Setting up Office 365 based Development Environment</h4> <p>You can find more details of how to setup the development environment from the link ‘<a href="http://msdn.microsoft.com/en-us/library/jj163980%28v=office.15%29.aspx" target="_blank">Get Started developing apps for SharePoint</a>’. But I’ve put the details below, in more precise steps:</p> <ul> <li><b>Step 1</b>: Sign up for office 365 developer site as instructed here: ‘<a href="http://msdn.microsoft.com/en-us/library/fp179924(v=office.15).aspx" target="_blank">Sign Up for an Office 365 Developer Site</a>’ <br /></li> <li><b>Step 2</b>: Once you finish signup, please navigate to the URL(if you are not already redirected), <a title="https://portal.microsoftonline.com/default.aspx" href="https://portal.microsoftonline.com/default.aspx">https://portal.microsoftonline.com/default.aspx</a>. then login with your office365 user id. <br /></li> <li><b>Step 3</b>: From the link <a title="https://portal.microsoftonline.com/default.aspx" href="https://portal.microsoftonline.com/default.aspx">https://portal.microsoftonline.com/default.aspx</a>, please click ‘Build Apps on the developer site.’ link as shown in the image below: </li> </ul> <blockquote><a href="http://lh3.ggpht.com/-l6I_4q91Fz8/UI0pb8kCgzI/AAAAAAAAA5U/wU4i0O2Fmkc/s1600-h/image%25255B19%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-tYJV-0gw3Dg/UI0pcofejgI/AAAAAAAAA5c/3dc_zt-z0f4/image_thumb%25255B9%25255D.png?imgmax=800" width="765" height="424" /></a> <br /><b>Figure 3: Office 365 admin center <br /></b></blockquote> <ul> <li><b>Step 4</b>: Now you will be landed to the SharePoint developer site and from the site click the tile ‘Get tools to build apps’ as shown below: </li> </ul> <blockquote><a href="http://lh4.ggpht.com/-SisiJgEqGng/UI0pd_KPaFI/AAAAAAAAA5k/7Sx2kINkKcY/s1600-h/image%25255B23%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-WzeXC4rdlf8/UI0pg_ztbLI/AAAAAAAAA5s/OYUMGUwGytA/image_thumb%25255B11%25255D.png?imgmax=800" width="761" height="499" /></a> <br /><b>Figure 4: SharePoint developer site in Office 365 preview <br /></b></blockquote> <ul> <li><b>Step 5</b>: On the details page install ‘Napa – office 365 developer tools’. <br /></li> <li><b>Step 6</b>: Once installation is finished, click ‘Site contents’ from left side and then launch the app “Napa – office 365 developer tools’ by clicking as shown below: </li> </ul> <blockquote><a href="http://lh5.ggpht.com/--mS0MVYRNIo/UI0ph2hIcXI/AAAAAAAAA50/xvfiTlG5XaI/s1600-h/image%25255B31%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-RgkEpQVUe1w/UI0pjNCE_7I/AAAAAAAAA58/eM7Csua-cOU/image_thumb%25255B15%25255D.png?imgmax=800" width="745" height="429" /></a> <br /><b>Figure 5: Launch ‘Napa developer tools’ from Site contents</b> <br /></blockquote> <ul> <li><b>Step 7</b>: Once the app launches, you can add the new SharePoint app project by clicking link’ Add New Project’ as shown below: </li> </ul> <blockquote><a href="http://lh4.ggpht.com/-HR52kj98tXA/UI0pkFMamBI/AAAAAAAAA6A/hCiAsgv2OQg/s1600-h/image%25255B35%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-sbc1CPoNGPc/UI0plF7LpsI/AAAAAAAAA6M/CIy-TKr_Bqw/image_thumb%25255B17%25255D.png?imgmax=800" width="543" height="393" /></a> <br /><b>Figure 6: Napa apps – home page <br /></b></blockquote> <ul> <li><b>Step 8</b>: Once the project created you will be provided in-browser IDE like development environment. However you can lunch the project in Visual Studio by clicking the icon ‘Open in Visual Studio’ as shown below. This will install necessary tools to run the project. </li> </ul> <blockquote><a href="http://lh5.ggpht.com/-Wr98TFIaN9c/UI0pmEmDKYI/AAAAAAAAA6Q/qvEBao4qdqg/s1600-h/image%25255B38%25255D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-gkR3CQdvvK4/UI0pmxjYehI/AAAAAAAAA6c/81IqRAaYCuk/image_thumb%25255B18%25255D.png?imgmax=800" width="231" height="107" /></a> <br /><b>Figure 7: Open in Visual studio link</b></blockquote> Finally Microsoft Web Platform Installer will run and install every required components to run the app. After the installation is done, you can deploy your app in Office 365 developer site. Just run your app from visual Studio by pressing F5, which will install the app before running and as soon as you stop debugging, the app will be uninstalled. <br /> <br /> <h4>Conclusion</h4> Setting up on-premises development environment requires manual configuration and might be time consuming. But setting up Office 365 based development environment is much easier and you can get it ready within 15-30 minutes. So I would recommend you to go for this Office 365 based setup to start learning how to develop apps. Once you are confident with the apps development you can also try to setup on-premises development environment. Anonymoushttp://www.blogger.com/profile/15485221969375347012noreply@blogger.com0