Blogger

  • This email address is being protected from spambots. You need JavaScript enabled to view it.

    Recent items

Login

Friday, 04 April 2014 07:51

Windows Azure: configure endpoints

Written by

Windows Azure is the Cloud platform of Microsoft.

I've a virtual machine with windows server 2012 R2 and SharePoint 2013 and I use it to prepare demos, to share environment with my team, make tests, etc. Very often I need to navigate my test environment with a public url and I use the Fully Qualified Domain Name of the machine.

The problem generally is to have on the same URL more sites that need to be available. The solution is to use:

  • alternate access mapping (AAM) on SharePoint with a particula port (>1024)
  • Add the binding for the site on IIS  with the same port specified on the AAM
  • allow that port on the Windows Firewall.

At this point, the last action to is to go on the azure web platform, select the virtual machine and you need to add an endpoint where you are mapping a public port (that will be used through the internet) with the port specified in IIS and on the AAM.

Et voila, now you can navigate the site via internet by a specific port.
For each site that you need to navigate by internet, you need to make the previous steps with a different port.

Note: if you have "Timeout error" when you surf the site via Internet, you need to check that on the Windows Server Firewall is added the exception for the port that the site is using.

Tuesday, 04 March 2014 22:46

How to use and configure large lists

Written by

Sometime,

we need to store into lists a lot of elements. All developers that know SharePoint knows that in the OOB views there is the limit of 5000 items.
I want suggest these recommendations to create a definition for a list that have a lot of elements:

  • allow the folders and create an event receiver in order to store the items into the folders (maximum 5000 items for each folder)
  • enable one o more indexed columns (not on the ID field and the best fields are text fields). Each column that will be used for where condition or $filter condition need to enabled as indexed column
  • if you are quering on lookup column, you must use this

<FieldRef Name='ColumnName' LookupId='TRUE' /><Value Type='Integer'   >LOOKUP_ITEM_ID</Value>

In the case that you have already the list and you have exceeded the threshold, these are the steps for the work around:

  • from the central administration, modify the threshold value up to the current list count on the current web application
  • add the indexed column
  • create a view that contains less of 5000 items (for example with where condition on created date)
  • from the central administration, reset the threshold value to 5000 on the current web application

In the case that you want to use the REST API on the list, remember that all fields that you need to apply $filter condition, need to defined as indexed column, otherwise you'll have the error "Internal server error".


See these links for more details

Hi,

today I'm working with a new project and the specification from the project is to develop a new application with SharePoint 2013 Foundation.

I've already a virtual machine but with SharePoint 2013 Enterprise.

I've two basic possibility:

  1. create a new virtual machine
  2. uninstall the Enterprise version of SharePoint and install the Foundation.

I've used the second approach. So I've uninstalled SharePoint 2013 Enterprise version and immediately after I've installed the Foundation version.

Just during the Wizard, I've received some errors: "dll not found", "files from feature not found", etc.

The problems stem from the fact that into the "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\" folder there are the definitions of both versions of SharePoint. Infact, when you uninstall SharePoint, the uninstaller does not remove the files and the folders into the path.

To make a clean installation, I've:

  • removed both versions
  • turned off the machine
  • mounted the vhd and removed the folder "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\" (It cannot be removed when the machine is turned on)
  • installed the SharePoint Foundation version
  • launched the wizar.

Finally, I've an installation and an usage without errors.

You may have encountered a warning similar to the following when browsing web sites with IE or Chrome:

"The Web site wants to run the following add-on: 'Name ActiveX Control' from 'Microsoft Corporation'. If you trust the Web site and the add-on and want to allow it to run, click here..."

The problem occurs only on PC that has Microsoft Lync installed. Infact, the browser needs the rights to execute a Microsoft dll (Name.dll) in order to display the presence icon.

I've also tried to disable the feature from the web application settings but it not resolve the problem.

If your application doesn't need of this feature and you want to disable this warning, you need to override the SharePoint OOB script that request the add-on. These are the steps to fix the problem:

  • Edit the master page
  • immediately under the body tag, add the follow script.

Show/Hidden javascript code

View source
 
 
 
<script>
    function ProcessImn()
    { }
    function ProcessImnMarkers()
    { }
</script>  
 
 
 

That is it.

Saturday, 23 November 2013 13:48

Resize VHD free space

Written by

Many thanks to This email address is being protected from spambots. You need JavaScript enabled to view it. for the solution of the problem.

If you are working with SharePoint and if you are developing by virtual machine then probably you may think to use a SSD (mine 128gb) to contain the VHD file and speedup your work. This is my case but the VHD dynamic expansion causes this

The principal problem is the impossibility to start up the virtual machine because it gives me a critical error and i cannot fix this problem (probably deleting some big files) internally.

Then I found this solution to resize and compact the VHD:

  • Start CMD as administrator
  • Prompt:diskpart
  • select vdisk file=<your drive>:\<your path>\<filename>.vhd   (ex. F:\MyVM\win8.vhd)attach vdisk readonly
  • compact vdisk
  • detach vdisk

Good. After this, the vhd size is passed from 110gb to 109.6gb. Not a good result, but I re-launched the VM and it was started. Just the time to find and delete some big files (first of all old content db). I repeated the step to reduce the size of VHD and

Enjoy it! Risatona

Tuesday, 19 November 2013 11:10

Enable mobile access to anonymous zone

Written by

SharePoint 2010 has two visualization types:

  • Desktop
  • Mobile

For the mobile view, the system provide to read the user agent and redirect the requestes to a system pages that after redirect the requestes to the mobile views (for the lists, doc libraries, etc.).

If you wanto to give the desktop view also to the mobile terminal to the anonymous zones, with the OOB settings you have an access denied because the system redirect your requestes to a system pages that is under permission. If you try to access to the public portal with a mobile terminal (with a desktop terminal you don't have problems), you receive the popup for the credentials.

So, to enable the view also for the mobile terminal, you need to modify the web.config file for each Web Front End.

Under the section

Show/Hidden xml code

View source
 
 
 
<configuration>
 
<system.web>
 
<browserCaps>
 
              <result type="System.Web.Mobile.MobileCapabilities, System.Web.Mobile, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
 
              <filter>isMobileDevice=false</filter>
 
</browserCaps>
 
...
 
</system.web>
 
 
</configuration>
 
 
 

Friday, 25 October 2013 17:24

Another "special" thanks to Windows Updates

Written by

Some days ago, my collegue This email address is being protected from spambots. You need JavaScript enabled to view it. told me that his SkyDrive Pro cannot sync the new folder on the SharePoint.

He received the error "Sorry, we can't sync this library because it's hosted on a sharepoint 2010 server". I've sayed him that it could be a skydrive problem or that he is not a good programmer :P but today I've received the some errors.

After some searches, I've found that the problem encourred after some windows updates (on SkyDrive Pro application).

In my mind I think: "how is possible that after the windows updates, one time some SharePoint doesn't work and now the SkyDrive".

The first clean solution is to uninstall the updates. In my case they are 6 and are all called with KB2825633. I've closed the SkyDrive Pro and reopen it (without restarting windows) and now I'm able to sync my document library.

 

 

 

Thursday, 17 October 2013 17:45

My first Office365 App

Written by

Today, I started to develop and deploy my first App for SharePoint online into Office 365.

After the creation of some test files, it would be the time to deploy the app and Visual Studio shows me the first error:

"Error occurred in deployment step 'Install app for SharePoint': Sideloading of apps is not enabled on this site."

After some searches on google, I understand that I need to enable an hidden feature if I want to use the development site. I need to download and install the "SharePoint Online Management Shell".

I've installed it, i've run and I've received another error (now from the SharePoint online powershell):

"Import-Module : Could not load type 'Microsoft.SharePoint.Administration.SiteHealth.SiteHealthStatusType' from assembly 'Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'."

At this point, google does not help me.

The solution is to NOT use the SharePoint online shell directly but from the SharePoint 2013 Management Shell and use this script:

Show/Hidden bash code

View source
 
 
 
#CODE STARTS HERE
 
 
$programFiles = [environment]::getfolderpath("programfiles")
 
 
add-type -Path $programFiles'\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll'
 
 
Write-Host 'To enable SharePoint app sideLoading, enter Site Url, username and password'
 
$siteurl = Read-Host 'Site Url'
 
$username = Read-Host "User Name"
 
$password = Read-Host -AsSecureString 'Password'
 
 $outfilepath = $siteurl -replace ':', '_' -replace '/', '_'
 
try
{
 [Microsoft.SharePoint.Client.ClientContext]$cc = New-Object Microsoft.SharePoint.Client.ClientContext($siteurl)
 
 [Microsoft.SharePoint.Client.SharePointOnlineCredentials]$spocreds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
 
 $cc.Credentials = $spocreds
 
 Write-Host -ForegroundColor Yellow 'SideLoading feature is not enabled on the site:' $siteurl
 
 $site = $cc.Site;
 
 $sideLoadingGuid = new-object System.Guid "AE3A1339-61F5-4f8f-81A7-ABD2DA956A7D"
 
 $site.Features.Add($sideLoadingGuid, $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None);
 
 $cc.ExecuteQuery();
 
 Write-Host -ForegroundColor Green 'SideLoading feature enabled on site' $siteurl
 #Activate the Developer Site feature
}
 
catch
 
{ 
 Write-Host -ForegroundColor Red 'Error encountered when trying to enable SideLoading feature' $siteurl, ':' $Error[0].ToString();
}
 
 
#CODE ENDS HERE
 
 
 

 

 

This is a brief description to how generate an image of a SharePoint aspx page (or part of page).

This is the main class that provide to generate an image starting from the aspx page

Show/Hidden csharp code

View source
 
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using Microsoft.SharePoint;
 
namespace lucacostante.com
{
    public class ASPXToImage
    {
        private Bitmap bitmap;
        private string url;
        private string fileName = string.Empty;
        private string startFromID = string.Empty;
        private Control control = null;
 
 
        public ASPXToImage(string url, string fileName)
        {
            this.url = url;
            this.fileName = fileName;
        }
 
        public Bitmap GenerateFull()
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
               {
                   using (SPSite site = new SPSite(this.url))
                   {
                       using (SPWeb w = site.OpenWeb())
                       {
                           // Thread 
                           var m_thread = new Thread(Generate);
                           m_thread.SetApartmentState(ApartmentState.STA);
                           m_thread.Start();
                           m_thread.Join();
                       }
                   }
               });
            return bitmap;
        }
 
 
 
        public Bitmap GeneratePagePart(string partIdOrClass)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
               {
                   using (SPSite site = new SPSite(this.url))
                   {
                       using (SPWeb w = site.OpenWeb())
                       {
                           this.startFromID = partIdOrClass;
 
                           // Thread 
                           var m_thread = new Thread(GeneratePart);
                           m_thread.SetApartmentState(ApartmentState.STA);
                           m_thread.Start();
                           m_thread.Join();
                       }
                   }
               });
            return bitmap;
 
        }
 
        private void Generate()
        {
            var browser = new WebBrowser { ScrollBarsEnabled = false };
            browser.Navigate(url);
            browser.DocumentCompleted += WebBrowser_FullDocumentCompleted;
 
            while (browser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }
 
            browser.Dispose();
        }
 
        private void GeneratePart()
        {
            var browser = new WebBrowser { ScrollBarsEnabled = false };
            browser.Navigate(url);
            browser.DocumentCompleted += WebBrowser_PartDocumentCompleted;
 
            while (browser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }
 
            browser.Dispose();
        }
 
        private void WebBrowser_FullDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Capture 
            var browser = (WebBrowser)sender;
            int width = browser.Document.Body.ScrollRectangle.Width;
 
            int height = browser.Document.Body.ScrollRectangle.Bottom;
 
            GenerateImage(browser, width, height);
        }
 
        private void WebBrowser_PartDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Capture 
            var browser = (WebBrowser)sender;
 
            HtmlElement found = FindIdOrClass(browser, startFromID);
 
            if (found != null)
            {
                GenerateImage(browser, found);
            }
        }
 
 
        private HtmlElement FindIdOrClass(WebBrowser browser, string startFromID)
        {
            HtmlElement found = null;
 
            found = (from HtmlElement ele in browser.Document.All
                     where ele.Id == startFromID ||
                     ele.GetAttribute("className") == startFromID
                     select ele).FirstOrDefault();
 
 
            return found;
        }
 
        private void GenerateImage(WebBrowser browser, int width, int height)
        {
            browser.ClientSize = new Size(width, height);
            browser.ScrollBarsEnabled = false;
            bitmap = new Bitmap(width, height);
            browser.BringToFront();
 
            browser.DrawToBitmap(bitmap, browser.Bounds);
 
            // Save as file? 
            if (this.fileName.Length > 0)
            {
                // Save 
                bitmap.SaveJPG100(this.fileName);
            }
        }
 
        private void GenerateImage(WebBrowser browser, HtmlElement ele)
        {
            Rectangle rec = ele.OffsetRectangle;
 
            int width = browser.Document.Body.ScrollRectangle.Width;
            int height = browser.Document.Body.ScrollRectangle.Bottom;
 
            CalculateSize(browser.Document.Body, ref width, ref height);
 
            int y = 0;
            int x = 0;
            int previewOffsetX = 0;
            int previewOffsetY = 0;
            HtmlElement parent = ele;
 
 
            while (parent != null)
            {
                if (parent.OffsetRectangle.Top != previewOffsetY)
                    y += parent.OffsetRectangle.Top;
                if (parent.OffsetRectangle.Left != previewOffsetX)
                    x += parent.OffsetRectangle.Left;
 
                previewOffsetX = parent.OffsetRectangle.Left;
                previewOffsetY = parent.OffsetRectangle.Top;
 
                parent = parent.Parent;
 
            }
            Rectangle rect = new Rectangle(x / 2, y, ele.OffsetRectangle.Width, ele.OffsetRectangle.Height);
 
            width = (ele.OffsetRectangle.Width + x > width) ? ele.OffsetRectangle.Width + x : width;
 
            browser.ClientSize = new Size(width, height);
 
            using (Bitmap bitmap = new Bitmap(browser.Width, browser.Height))
            {
                browser.DrawToBitmap(bitmap, new Rectangle(0, 0, browser.Width, browser.Height));
                Bitmap cropped = bitmap.Clone(rect, bitmap.PixelFormat);
                cropped.Save(this.fileName, ImageFormat.Jpeg);
            }
        }
 
        private void CalculateSize(HtmlElement currElement, ref int width, ref int height)
        {
            if (currElement.Children != null && currElement.Children.Count > 0)
            {
                foreach (HtmlElement element in currElement.Children)
                {
                    if (element.ScrollRectangle.Width > width)
                        width = element.ScrollRectangle.Width;
 
                    if (element.ScrollRectangle.Bottom > height)
                        height = element.ScrollRectangle.Bottom;
 
                    CalculateSize(element, ref width, ref height);
                }
            }
        }
 
    }
 
 
    public static class BitmapExtensions
    {
        public static void SaveJPG100(this Bitmap bmp, string filename)
        {
            var encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
            bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
        }
 
        public static void SaveJPG100(this Bitmap bmp, Stream stream)
        {
            var encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
            bmp.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters);
        }
 
        public static ImageCodecInfo GetEncoder(ImageFormat format)
        {
            var codecs = ImageCodecInfo.GetImageDecoders();
 
            foreach (var codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                {
                    return codec;
                }
            }
 
            // Return 
            return null;
        }
    }
}
 

In my case, after the page creation, I've uploaded the image into the Image document library and after I've redirect the user to its url.

This is the print screen:

When I click on "Generate Image" ribbon button, The syste create the image taking the information in a div with the id "previewBody".

This is the code to generate, upload and redirect to the generated image

Show/Hidden csharp code

View source
 
 
 
protected void GenerateImage()
        {
            string path = Environment.GetEnvironmentVariable("TEMP") + @"\" + (Guid.NewGuid().ToString("N"));
            ASPXToImage websiteToImage = new ASPXToImage(Request.Url.AbsoluteUri, path);
            websiteToImage.GeneratePagePart("previewBody");
 
            byte[] fileContents;
            SPSecurity.RunWithElevatedPrivileges(delegate()
             {
                  using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                   {
                       using (SPWeb web = site.OpenWeb())
                       {
                           if (System.IO.File.Exists(path))
                           {
                               SPList images = web.Webs["newsletter"].Lists["Images"];
 
                               bool successfully = false;
                               SPFile file;
                               using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
                               {
                                   int length = (int)fileStream.Length;  // get file length
                                   fileContents = new byte[length];            // create buffer
                                   int count;                            // actual number of bytes read
                                   int sum = 0;                          // total number of bytes read
 
 
                                   // read until Read method returns 0 (end of the stream has been reached)
                                   while ((count = fileStream.Read(fileContents, sum, length - sum)) > 0)
                                       sum += count;  // sum is a buffer offset for next reading
 
                                   images.ParentWeb.AllowUnsafeUpdates = true;
 
 
                                   file = images.RootFolder.Files.Add(Guid.NewGuid().ToString("N") + ".jpg", fileContents, true);
 
                                   images.ParentWeb.AllowUnsafeUpdates = false;
 
                                   if (file != null)
                                   {
                                       successfully = true;
                                   }
                               }
                               if (successfully)
                               {
                                   System.IO.File.Delete(path);
                                   Response.Redirect(SPContext.Current.Web.Url + "/" + file.Url);
                               }
                           }
                       }
                 }
             });
        }
 
 
 

This is the result

Note: During the deploy in production, this feature does not work because it need the credentials and the WebBrowser does not allow the NTLM access (infact it loops into while cicle).

To  resolve the problem, there are two possible solution:

  1. Allow Basic authentication and pass the credentials to the WebBrowser object
  2. extend the WebApplication with an anonymous zone. Allow the navigation of this zone only into the current server. put the logic that the image will be generated into the anonymous zone.

 

Page 2 of 4