DCSIMG
Doron Goldberg

Organization browser web part can be easily used inside pages of the portal with default behavior of showing the current user as the selected profile which appears in the center of the organization browser when the page loads.

However, sometimes you might prefer to show a different user by default, for example – a department’s page where the manager is shown with all his employees. Unfortunately, the organizational browser web part does not come with suitable properties which allows us to tweak the web part.

Microsoft made an effort to make it hard to change it and even after I opened the hierarchychart.xap file I couldn’t find any way to go around the problem.

After playing with the web part and comparing the same page with and without the web part I came to a solution which allowed me to display the organization browser with a selected profile of my choice. In order to achieve this goal I used the content editor web part which loads a static htm file with the following code which than creates the organizational browser.

The code has2 main regions:

1) The JavaScript which usually rendered by the web part is responsible for loading the control. One thing you need to change is the url of the current site (see highlighted text).

2) The html code contains the <object> and <input> which is required for some reason (probably accessed from Silverlight somehow). Notice you have 2 locations where you need to type the root user in domain\user format.

<script>
    function
OnHierarchyChartLoaded(sender) {
        var params = sender.GetHost().InitParams.split(',');
        var profileId = params[0];
        var profileType = params[1];
        var persistControlId = params[2];

        sender.GetHost().content.HierarchyChartObject.SetPersistControlId(persistControlId);
        sender.GetHost().content.HierarchyChartObject.SetProfileServiceUrl('http://yousiteurl');

        // Check if this is returning session, pulling out profile from cookie
      
var lastVisitedProfile = GetLastVisitedProfile(persistControlId)
        if(lastVisitedProfile != null) {
            params = lastVisitedProfile.split(',');
            if(params.length > 1) {
                profileId = params[1];
                profileType = params[0];
            }
        }

        sender.GetHost().content.HierarchyChartObject.SetNewProfile(profileId, profileType);
    }

    functionHideControls(controlIds) {
        for(i = 0; i < controlIds.length; i++) {
            var control = document.getElementById(controlIds[i]);
            if(control != null) {
                control.style.display = 'none';
            }
        }
    }

    functionGetLastVisitedProfile(persistControlId) {
        var control = document.getElementById(persistControlId);
        returncontrol.value;
    }
</script>
<
inputname="ctl00_customorgbrowser_ctl00"title="This web part displays an interactive view of your company's users and organizations. A preview is unavailable for this web part because it requires Silverlight."id="ctl00_customorgbrowser_ctl00"style="display: none;position: absolute;"type="text"value="User,domain\user"/>
<
objectwidth=600"height="600"id="ProfileBrowserSilverlightControl2"data="data:application/x-silverlight,"type="application/x-silverlight">
<
param name="top"value="30"/>
<
param name="enableHtmlAccess"value="true"/>
<
param name="source"value="/_layouts/ClientBin/hierarchychart.xap"/>
<
param name="initParams"value="domain\user,User,ctl00_customorgbrowser_ctl00"/>
<
param name="windowless"value="true"/>
<
param name="onLoad"value="OnHierarchyChartLoaded"/>
</
object>

Once uploading the html file to a document library it can be used to display the organizational browser using a content editor.

Posted by dorong | 1 comment(s)

After building the Treeview and connecting it to the selected item inside the Lightswitch screen I wanted to extend the control so it will show images along with the textual labels.

Same as the label value, my images are also stored inside Lightswitch as a property. In my case a sub-property of the “Site” property. (In my case each position is attached to a site, which has an image representing the flag of the site’s location – and I’m building a positions tree!)

My sites List Details screen looks something like that:

sites

 

Since the Silverlight Image control takes a BitmapImage as source a small converter is required to create the BitmapImage from the data stored inside Lightswitch:

using System;
using System.Windows.Data;
using Microsoft.LightSwitch;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Media.Imaging;
using System.Text;
using System.IO;

namespace SilverLightControls
{
 
    public class SiteImageConverter : IValueConverter
    {
        public static BitmapImage ImageFromBuffer(Byte[] bytes)
        {
            MemoryStream stream = new MemoryStream(bytes);
            BitmapImage image = new BitmapImage();     
            image.SetSource(stream);   
            return image;
        }
        public static SiteImageConverter Instance =
            new SiteImageConverter();

        public object Convert(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            byte[] imageArray=value as byte[];
            return ImageFromBuffer(imageArray);
        }
        public object ConvertBack(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            throw new NotSupportedException("Cannot convert back");
        }
    }
}

Simple code: convert the value to a byte[] (this is how it is stored), create a bitmap out of it and return the bitmap.

 

The XAML file has the related parts highlighted so you can see how can you bind the control to the image.:

<UserControl x:Class="SilverLightControls.PositionsTree"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverLightControls"    
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="clr-namespace:System.Windows;assembly=System.Windows.Controls" 
    xmlns:controls="clr-namespace:SilverLightControls"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <local:EntityCollectionValueConverter x:Key="EntityCollectionValueConverter" />
        <local:SiteImageConverter x:Key="SiteImageConverter" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel  Orientation="Horizontal">
            <controls:AutoExpandingTreeView Name="positionsTree" ItemsSource="{Binding Screen.PositionsTree}" >
                <controls:AutoExpandingTreeView.ItemTemplate>
                    <toolkit:HierarchicalDataTemplate 
                            ItemsSource="{Binding 
                        Converter={StaticResource EntityCollectionValueConverter}, 
                        ConverterParameter=Positions}">
                        <StackPanel  Orientation="Horizontal">
                            <Image Name="img"  Width="15" Height="15" Stretch="Fill" Source="{Binding Site.SiteFlag,Converter={StaticResource SiteImageConverter}}"/>
                            <TextBlock  Text="{Binding Path=PositionName, Mode=TwoWay}" 
                                       Margin="5,0" Width="150" />
                        </StackPanel>
                        </toolkit:HierarchicalDataTemplate>
                </controls:AutoExpandingTreeView.ItemTemplate>
            </controls:AutoExpandingTreeView>
        </StackPanel>
    </Grid>

</UserControl>

And the result:

positions

Posted by dorong | with no comments

In his great article “Hierarchical Data with LightSwitch” Michael Washington is demonstrating how Lightswitch can be extended using custom Silverlight controls. The article helps to build a tree view control for displaying hierarchical information such as departments, categories etc. 

After implementing the solution I wanted to extend the tree view so it will effect the screen itself and refresh the selected item data according to the selected node in the tree (The solution brought in the article only describes the ability to refresh the tree view when items are updated or added to the list).

(I used my tree view to display hierarchical categories in my application so the code will reference the items as “categories”)

Making calls from custom Silverlight controls to methods defined inside a Lightswitch screen is easy:

  1. add a method to the screen
  2. call the method using the following format from the control:

var objDataContext = (IContentItem)this.DataContext;
var Screen =
   (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
Screen.Details.Dispatcher.BeginInvoke(() =>
{
    Screen.Details.Methods["UpdateSelectedDepartment"].CreateInvocation().Execute();
        
});

Using method invocation you can call methods defined on the screen but the only problem is those methods don’t have properties – something which is required in this case since we want UpdateSelectedDepartment to knows what the selected department is.

This can be handled in two ways, the first one (which I will not bring here) involves altering internal files so the invoked method will refer to passed arguments – it worked for me but it was very unstable.

The second method (which I’m currently using) was to do the following:

  1. Add a parameter typed as the selected value in the tree view to the screen (In may case parameter called SelectedDepartment of type “Department”).
  2. Add a method to the screen which will be invoked by the control (In my case I named it UpdateSelectedDepartment).
  3. Add The following code to the method:

partial void UpdateSelectedDepartment_Execute()

{

   Departments.SelectedItem = this.SelectedDepartment;

}

  1. Use the following code inside the Silverlight control:

public SilverlightTreeControl()

{

  InitializeComponent();

  treeViewControl.SelectedItemChanged += new RoutedPropertyChangedEventHandler(treeViewControl_SelectedItemChanged);

}

void treeViewControl_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object e>)

{

var objDataContext = (IContentItem)this.DataContext;

var Screen =
               (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;

Screen.Details.Properties["SelectedDepartment"].Value = e.NewValue;

Screen.Details.Dispatcher.BeginInvoke(() =>
            {
                Screen.Details.Methods["UpdateSelectedDepartment"].CreateInvocation().Execute();
        
            });

}

As you can see the solution is simple – update the selected department parameter, call the method, access the parameter and set the current item to be the parameter value.

Posted by dorong | 2 comment(s)

My “portal sharing web part” is a web part I’m currently working on which will allow users to interact socially with one another based on “my site” – directly from the portal itself.

The look will include 3 buttons for 3 actions:

  1. Upload an image
  2. Status update
  3. Post a survey

In this post I will focus on the 2nd button – status update. As you know “my site” now has a “users says” feature which is basically a status update:

image

Using my web part I wanted to allow users inside the corporate portal to update the status directly from the main page. This was done in order to bring the “my” experience closer to the working environment.

The web part looks something like that:

image

And when the 2nd button is clicked, jquery using the fadeIn() / fadeOut() effect brings the update status form:

image

Now all the user needs to do is type his new status and click “Update Status” which will use AJAX in order to update the status line inside the my site (and update the UI using jquery as well)

image

This solution has two main parts, server side for interacting with the my site settings and the client side for the nice UI / jquery effects.

Client Side

Client side is based on a simple visual web part which holds the JavaScript, CSS, Html and images:

image

The only “real” code in this web part is the one registering the scripts to the page header:

protected void Page_Load(object sender, EventArgs e)
     {
         HtmlGenericControl jquery = new HtmlGenericControl("script");
         jquery.Attributes["type"] = "text/javascript";
         jquery.Attributes["src"] = "_layouts/GeneralInfra/jquery.js";
         Page.Header.Controls.Add(jquery);
         HtmlGenericControl css = new HtmlGenericControl("link");
         css.Attributes["type"] = "text/css";
         css.Attributes["rel"] = "stylesheet";
         css.Attributes["href"] = "_layouts/PortalShareProject/PortalShare.css";
         Page.Header.Controls.Add(css);
         HtmlGenericControl js = new HtmlGenericControl("script");
         js.Attributes["type"] = "text/javascript";
         js.Attributes["src"] = "_layouts/PortalShareProject/PortalShare.js";
         Page.Header.Controls.Add(js);
 
 
      
     }
 

(Since it’s a fresh server I registered the jquery as well although in case you have it implemented somehow maybe through the master page or some kind of feature it’s not needed as part of the web part)

As you have noticed I’m addressing a second solution called “GeneralInfra”, I will come back to it for the server side discussion.

inside my “$(document).ready(function () {}” code the one related to the status update is:

$("#statusbutton").click(function () {
       if ($("#statusdiv").css('display') == 'none') {
           $("#picdiv").fadeOut('slow', function () {
               $("#surveydiv").fadeOut('slow', function () {
                   $("#statusdiv").fadeIn();
               });
           });
       }
       else {
           $("#statusdiv").fadeOut();
       }
   });

this code is for the fade in / fade out effect which brings the status update form.

 

For getting the current status I’m using a simple ajax call:

$.get("/_layouts/GeneralInfra/MyStatus.aspx", function (data) {
      $("#currentstatus").html('<i>' + data + '</i>');
  });

When the update status is clicked I have this piece of code for handling the ajax call:

$("#updatestatus").click(function () {
 
      $.get("/_layouts/GeneralInfra/MyStatus.aspx", { status: $("#newstatus").attr('value') }, function (data) {
          $("#newstatus").val('');
          $("#currentstatus").html('<i>' + data + '</i>');
      });
 
      // $("#newstatus").attr('value')
  });

Before moving on the server side, HTML & CSS are:

<img class="sharemenubutton" src="_layouts/Images/PortalShareProject/photo.png" id="picturebutton">
<img class="sharemenubutton" src="_layouts/Images/PortalShareProject/status.PNG" id="statusbutton">
<img class="sharemenubutton" src="_layouts/Images/PortalShareProject/url.PNG" id="surveybutton">
 
<div>
 
<div class="PortalShare_Section" id="picdiv">
<div id="closepic"  class="closediv">[x]</div>
Select an image you wish to share and click post:<br /><input type="file" class="portalsharebutton" /><input type="button" value="Upload" class="portalsharebutton" />
</div>
 
<div class="PortalShare_Section" id="statusdiv">
<div id="closestatus" class="closediv">[x]</div>
Your current status:
<br /><br />
<div id="currentstatus"></div>
<br />
<input id="newstatus" type="text"  class="portalsharetextbox" /><input id="updatestatus" type="button" value="Update Status" class="portalsharebutton" />
</div>
 
<div class="PortalShare_Section" id="surveydiv">
<div id="closesurvey"  class="closediv">[x]</div>
Question:
<br />
<input type=text class="portalsharetextbox" /><br />
<ul id="answers"></ul>
<input type=text id="answer" class="portalsharetextbox"/>
<input id="addanswerbutton" type="button" value="Add answer" class="portalsharebutton"  />
<br />
<br />
Type a survey question, add optional answers if you like and click publish to post it to your my site
<br />
<div class="closediv">
<input type="button" value="Publish" class="portalsharebutton"  />
</div>
<br />
</div>
</div>
 
body
{
}
.PortalShare_Section
{
    display: none;
    width:400px;
    border-radius: 15px;
    -moz-border-radius: 15px;
    background-color:#EEE;
    padding:10px;
    height:170px;
    vertical-align:top;
    padding-top:30px;
}
.closediv
{
    float:right;
    cursor:pointer;
   
}
input.portalsharebutton
{
    
   font-size:11px;
   font-family:Tahoma,sans-serif;
   color:#666666;
   height:20px;
   background-color:#CCCCCC;
   border-top-style:solid;
   border-top-color:#888888;
   border-top-width:1px;
   border-bottom-style:solid;
   border-bottom-color:#888888;
   border-bottom-width:1px;
   border-left-style:solid;
   border-left-color:#888888;
   border-left-width:3px;
   border-right-style:solid;
   border-right-color:#888888;
   border-right-width:1px;
   
 
}
input.portalsharetextbox
{
   font-size:11px;
   font-family:Tahoma,sans-serif;
   color:#666666;
   height:18px;
 
   border-top-style:solid;
   border-top-color:#888888;
   border-top-width:1px;
   border-bottom-style:solid;
   border-bottom-color:#888888;
   border-bottom-width:1px;
   border-left-style:solid;
   border-left-color:#888888;
   border-left-width:1px;
   border-right-style:solid;
   border-right-color:#888888;
   border-right-width:1px;
   width:280px;
}
.sharemenubutton
{
    cursor:pointer;
}
 

Server Side

For implementing the server side I have created an infrastructure module project which holds the jquery file and any other infrastructures files I might need in the future.

Currently it only serves this web part so it looks like this:

image

What interests us is the MyStatus.aspx application page. (I used it because it was faster to implement although I’m planning to switch into a web service)

Using an application page made the ajax part easier to implement as well and since the operations are not complex – get status / set status I went along with it.

The code is very simple – if a status was provided –> update the status, if not –> return the current status:

public string GetStatus()
       {
           string statusMessage = string.Empty;
           string socialDataStatsSite = SPContext.Current.Site.Url;
           using (SPSite siteColl = new SPSite(socialDataStatsSite))
           {
               SPServiceContext serviceContext = SPServiceContext.GetContext(siteColl);
 
               UserProfile userProfile = ProfileLoader.GetProfileLoader().GetUserProfile();
               SPContext.Current.Web.AllowUnsafeUpdates = true;
               if (userProfile[PropertyConstants.StatusNotes] != null)
               {
                   statusMessage = userProfile[PropertyConstants.StatusNotes].Value.ToString();
               }
           }
           return statusMessage;
       }
     
       public static void SetStatus(string statusMessage)
       {
           string socialDataStatsSite = SPContext.Current.Site.Url;
           using (SPSite siteColl = new SPSite(socialDataStatsSite))
           {
               SPServiceContext serviceContext = SPServiceContext.GetContext(siteColl);
               UserProfile userProfile = ProfileLoader.GetProfileLoader().GetUserProfile();
               SPContext.Current.Web.AllowUnsafeUpdates = true;
               userProfile[PropertyConstants.StatusNotes].Value = statusMessage;
             
               userProfile.Commit();
           }
       }
       protected void Page_Load(object sender, EventArgs e)
       {
           if (Request["status"] == null)
           {
               Response.Clear();
               Response.Write(GetStatus());
               Response.End();
           }
           else
           {
               Response.Clear();
               try
               {
                   SetStatus(Request["status"].ToString());
                   Response.Write( Request["status"].ToString());
               }
               catch (Exception ex)
               {
                   Response.Write(ex.Message);
               }
 
               Response.End();
           }
       }
 

That’s about it – a nice social web part for your portal’s front page.

Posted by dorong | with no comments

I recently came across a familiar situation where I needed to synchronize user profiles inside SharePoint 2010 so they will include the profile picture which is defined elsewhere.

Usually users have their pictures included inside the Active Directory either as an extended schema or as a field which holds the URL where the image can be found. These cases are covered and can be easily solved in various ways. One of them is described here (Hebrew) using FIM or here (English) using simple mappings.

My situation was different – my users images were stored on an external HR application which exposed them via a URL which contained a unique identifier of the user. In my case it was an internal employee ID although it could be email, login name etc.

The URL was something like that: http://ourhrapplication/userimage.aspx?employeeid=12345  where 12345 is that unique identifier.

In our case this field was also replicated inside Active Directory under the property “EmpId”.

MY solution for importing the profile images from the external HR system inside our SharePoint 2010 portal user profiles (and My Site) is based on two steps:

1) Powershell script for setting the PictureUrl property of the user profile with the profile image URL of the external system.

2) A powershell command which will resize the image and store it inside the My Site user profile images library.

 

The script looks something like this:

#Set up default variables
 
 #My Site URL
$mySiteUrl = "http://my.portal.corp/"
 #Unique identifier property name from AD, can be user name, email, employee id etc.
$uniqueIdentifier="EmpId"
 #Image url format with the unique identifier as {0}
$newPictureURL = "http://ourhrapplication/userimage.aspx?employeeid={0}"
 
 
 
#The internal name for PictureURL
$upPictureURLAttribute = "PictureURL"
 
#Get site objects and connect to User Profile Manager service
$site = Get-SPSite $mySiteUrl
$context = Get-SPServiceContext $site
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$profiles = $profileManager.GetEnumerator()
 
foreach ($userProfile in $profiles) {
 
f ((-not [System.String]::IsNullOrEmpty($userProfile[$uniqueIdentifier])) -and ([System.String]::IsNullOrEmpty($userProfile[$upPictureURLAttribute])))
{    
   $uniqueIdentifierValue=$userProfile[$uniqueIdentifier] 
   $formatedImageUrl=$newPictureURL -f $uniqueIdentifierValue 
   write-host "Image URL" :  $formatedImageUrl
 
   $userProfile[$upPictureURLAttribute].Value = $newPictureURL
   $userProfile.Commit()
 }
 
}

 

(I was inspired by a similar solution which also describes updating user profile properties via powershell)

 

The second step is to run a powershell command which is already provided by SharePoint:

Update-SPProfilePhotoStore –MySiteHostLocation “http://intranet/my/”

(You should run this command from the SharePoint management shell)

This command will go through all user profiles and update the images thumbnails according to the URL we defined in the previous step.

More on this can be found here: SharePoint 2010, Office 2010 and profile pictures. (This post will also direct you to your next stop – embedding profile pictures in exchange 2010 and Outlook 2010)

Hi,

After changing the EditForm.aspx & DispForm.aspx of a a list I’m working on something went terribly wrong:

All the links directing to the view item form / edit form are pointing to the root site without the form itself.

Meaning – instead of having a link to:

 http://myportal/mysubsite/Lists/MyList/DispForm.aspx?ID=1

I now have links pointing:

http://myportal/?ID=1

Same goes for editing item – when clicking ‘Edit Item’ the page redirects to the main page.

 

Searching for the cause came up with several ideas,for example, which none of them worked for me so far.

(The main cause is SPD)

 

So…

 

If you ever came across such a case and have a solution to offer – Please let me know.

 

Thank you!

Update:

The display item form values in SPD are correct as far as SPD can tell.

Update #2 – Solution:

here

Posted by dorong | 1 comment(s)

ptLogo

Job description

The candidate will be responsible for the SharePoint at Playtech

Implementation and maintenance tasks in the corporate Portal

Providing services to the corporate reference and management

Managing work with suppliers

Requirements

At least 3 years experience in large scale SharePoint implementation.

Proven experience in managing and maintaining enterprise portal based MOSS2007

Practical knowledge on SharePoint Designer

Knowledge of basic Web technologies HTML, CSS, etc.

Email me your CV if it interests you.

Posted by dorong | with no comments

After setting up a new web application for a new portal I faced a crawling problem of the new site collection.

Description:

Right after starting the crawler it stops, giving 2-3 error messages, all with the same syntax:

Error in the Site Data Web Service. (Value does not fall within the expected range.)

 

The crawl log was the only place the error was logged, with no additional information regarding the cause of the problem.

 

Searching the web came up with very little solutions, while only one of them seemed to apply to our case:

 

1. stsadm -o export -url http://intranet/sites/it -filename D:\it.back.11.21.08.cmp -versions 2
2. Delete the site collection
3. stsadm -o import -url http://intranet/sites/it -filename D:\it.back.11.21.08.cmp -updateversions 2 –nofilecompression

(See here)

 

While option 1 and 3 are reasonable, deleting the site collection didn’t apply since the portal was already in production stage. (along with the fact faze 1 didn’t pass either due to some technical issues… so I had to look for a better way to solve the issue)

After opening a support ticket, Microsoft’s support team came up with a nicer solution:

First of all, the cause behind this problem:

Corrupted SIDs in the UserInfo table

Solution:

1. Run the following sql query using your moss content database:

Select tp_login, tp_systemid, tp_deleted from userinfo where len(ltrim(rtrim(tp_systemid))) <25 and tp_deleted = 0

2. Give some kind of permissions to the root site of the site collection to all the users returned by the query, except system users:

NT AUTHORITY\authenticated users
NT AUTHORITY\local service
NT AUTHORITY\system
SHAREPOINT\system

4. After the query returns no results (accept the system accounts) start a full crawl.

 

Notes:

1. As for stage 2, you better test 2-3 users just to make sure that after you give them permissions to the root site they are infect removed from the query search results.

2. By give permission I mean any type of permission, “read” is enough. While giving permissions to a user in the root level the SID is updated and fixed (somehow…).

3. I had a local problem with some of the users which appeared in the returned result – I couldn’t add them to the site collection because they were deleted from the Active Directory (former employees) so simply had to delete them through the “People and Groups” of the site collection.

Posted by dorong | 9 comment(s)
תגים:, , ,

A few days ago we started migrating a portal site from one web application to another on the same machine.

As part of the migration process I needed to copy lists from the old site to the new site. Some lists, contained Person list columns, with single or multiple selection.

While the migration went smoothly during the export/import process itself the result was weird – all the user names were altered on the new portal.

 

Reason:

 

1. Person list columns store the user name (as text) and the user id from the profiles list.

2. Each web application has it’s own profiles – with different user id’s given to each user.

 

Instead of starting to migrate the profiles from one portal to another I simply wrote a small utility which fix the Person columns of selected lists (imported ones) by taking the user id, getting the email of the user from the old portal, finding the new user id on the new portal and updating the list item:

 

public partial class Form1 : Form
{
    private List<MigrationField> _migrationfields;
    private SPSite _sourcesite;
    private SPList _targetlist;
    private SPSite _targetsite;

    public Form1()
    {
        InitializeComponent();
        Source.Text = Settings.Default["SourceSite"].ToString();
        Target.Text = Settings.Default["TargetSite"].ToString();
    }
    private void btnVerifyColumns_Click(object sender, EventArgs e)
    {
        _sourcesite = new SPSite(Source.Text);
        _targetsite = new SPSite(Target.Text);
        _targetlist = _targetsite.RootWeb.GetList(TargetListUrl.Text);
        _migrationfields = new List<MigrationField>();
        Columns.Items.Clear();
        Log.Items.Clear();
        foreach (SPField field in _targetlist.Fields)
        {
            if (field.TypeAsString.Equals("User") || field.TypeAsString.Equals("UserMulti"))
            {
                Columns.Items.Add("Field Name: " + field.Title + ", Multi:" + field.TypeAsString.Equals("UserMulti"));
                _migrationfields.Add(new MigrationField { FieldName = field.Title, IsMulti = field.TypeAsString.Equals("UserMulti") });
            }
        }
        btnMigrate.Enabled = true;
    }

    private string GetEmailFromSource(string userid)
    {
        if (!String.IsNullOrEmpty(userid))
            return _sourcesite.RootWeb.SiteUsers.GetByID(Convert.ToInt32(userid)).Email;
        return String.Empty;
    }

    private SPUser GetUserFromTarget(string emailaddress)
    {
        if (!string.IsNullOrEmpty(emailaddress))
            return _targetsite.RootWeb.SiteUsers.GetByEmail(emailaddress);
        return null;
    }

    private void btnMigrate_Click(object sender, EventArgs e)
    {
        foreach (SPItem item in _targetlist.Items)
        {
            try
            {
                foreach (MigrationField field in _migrationfields)
                {
                    if (item[field.FieldName] != null)
                    {
                        switch (field.IsMulti)
                        {
                            case true:
                                string[] userids = item[field.FieldName].ToString().Split(';');
                                var userscollection = new SPFieldUserValueCollection();

                                for (int i = 0; i < userids.Length; i += 2)
                                {
                                    SPUser user = GetUserFromTarget(GetEmailFromSource(userids[i].Replace("#", "")));

                                    if (user != null)
                                        userscollection.Add(new SPFieldUserValue(_targetsite.RootWeb, user.ID,
                                                                                 user.Name));
                                }
                                item[field.FieldName] = userscollection;
                                item.Update();
                                break;
                            case false:
                                string email =
                                    GetEmailFromSource(item[field.FieldName].ToString().Substring(0,
                                                                                                  item[
                                                                                                      field.
                                                                                                          FieldName]
                                                                                                      .
                                                                                                      ToString().
                                                                                                      IndexOf
                                                                                                      (';')));
                                SPUser newuser = GetUserFromTarget(email);
                                if (newuser != null)
                                {
                                    item[field.FieldName] = newuser;
                                    item.Update();
                                }

                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Items.Add("itemid " + item.ID + ": " + ex.Message);
            }
        }
        MessageBox.Show("Done migrating");
    }
}
public class MigrationField
{
    public string FieldName { get; set; }
    public bool IsMulti { get; set; }
}
Posted by dorong | 3 comment(s)
תגים:, , , ,

A common thought is that in private browsing of IE 8 or incognito in chrome are meant to protect users from leaving their tracks behind.

From Microsoft:

InPrivate Browsing

When checking e-mail at an Internet café or shopping for a gift on a family PC, you don't want to leave any trace of specific web browsing activity. InPrivate Browsing in Internet Explorer 8 helps prevent your browsing history, temporary Internet files, form data, cookies, and usernames and passwords from being retained by the browser, leaving no evidence of your browsing or search history.“

From Google:

Explore Google Chrome features: Incognito mode (private browsing)

For times when you want to browse in stealth mode, for example, to plan surprises like gifts or birthdays, Google Chrome offers the incognito browsing mode.

  • Webpages that you open and files downloaded while you are incognito aren't recorded in your browsing and download histories.
  • All new cookies are deleted after you close the incognito window.”

Is it?

 

1. Go to “C:\Documents and Settings\{user-name}\Application Data\Macromedia\Flash Player\#SharedObjects\{some-hash-code}” and delete the some-hash-code folder.

2. Browse In-private using IE8 or Incognito using Chrome to some flash site (youtube for example)

3. Close the browser

4. See if the files were deleted…

 

 

(The same behavior was detected for Fire Fox’s private mode)

 

So, what happened?

It might be a bug or maybe some Macromedia workaround – In any case you should be more carful while browsing those flash sites. The files left behind are flash-cookies, sometimes saved in folders which renamed after the domain who created them…

And final note regarding IE8 In-Private browsing:

(since I’m not fully familiar with the parallel options of chrome & fire fox I’m not relating to them in this paragraph)

In-Private browsing feature is mainly focusing on protecting the user from being tracked by the server side, and not being tracked on the client side.

You should use In-Private browsing while trying to avoid sharing your information, such as browsing behavior, with 3rd party web sites of web sites you visit often in regular mode.

The discussed "”bug/feature/workaround” only make this argument more valuable.

 

* I would like to thank Shahar Bar for letting me know about the issue a while ago.

Posted by dorong | with no comments
תגים:,

Using regular returnValue methods is not working anymore for IE8.

While looking for the cause I came across a very nice and clean solution for doing that:

IE8 ModalDialog returnValue

Posted by dorong | with no comments

Since yesterday I keep getting a red screen when I use chrome telling me YNET may harm my computer.

The reason is elements from www.qdigital.co.il on the page which are marked as malware for some reason.

ynet

Posted by dorong | 5 comment(s)
תגים:

In case you came across a situation where you suddenly can’t browse your MOSS 2007 application locally, but still can access remote MOSS servers while others can access your application remotely:

KB963027

The solutions are:

1. Uninstall the update

2. Use IE6…

3. http://support.microsoft.com/kb/963027/ – read for more details

For more information see also:

http://blog.mpecsinc.ca/2009/04/sbs-2008-ie-update-kb963027-breaks.html

http://spiderwool.blogspot.com/

http://msmvps.com/blogs/bradley/archive/2009/04/16/sbs-2008-ie-update-kb963027-breaks-companyweb-access-from-the-server.aspx

Update: Another useful link:

http://support.microsoft.com/kb/896861/en-us

I would like to thank our people at Netwise: Avi Haimovich & Rani Of for the useful research of that matter.

Posted by dorong | 1 comment(s)
תגים:, , , ,

When trying to use ACT 5.5 Internet Explorer Compatibility Tool I got the following message:

“The file size exceeds the limit allowed and cannot be saved”

You can read about the problem here and download the hotfix needed in order to fix it here.

Posted by dorong | 1 comment(s)
תגים:, ,

While browsing using Internet Explorer 8, I received several times  xss filter notice saying: “Internet Explorer has modified this page to help prevent cross-site scripting” resulting an empty page, usually after trying to submit a form.

Although this is a security issue handled by IE in order to protect the user, sometimes it is blocking legit sites trying to do legit operations.

If you are a website owner and you received complains regarding this issue you can check your web site using ACT 5.5 AKA “Microsoft Application Compatibility Toolkit 5.5” which can be downloaded directly from here.

This is the result when using the Internet Explorer Compatibility Test Tool an my example web site:

image

As you can see the tool allows me to detect what happened and why during my browsing session inside my web site. (The tool also works on remote sites and can be used for solving other compatibility issues as well)

As for my example, I used the one I found on MSDN – here.

Resolution:

1. Fix your code and make sure you don’t perform illegal operations such as cross site scripting.

2. Ask you users to disable the xss filter on their machines (BAD!)

3. Set this response header: “X-XSS-Protection: 0” in order to disable this feature (BAD!)

You can set the response header directly from the web.config by adding this section:

<system.webServer> 

<httpProtocol>
    <customHeaders>
      <clear />
      <add name=" X-XSS-Protection" value="0" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Please make sure you read the MSDN article first so you’ll know exactly what the risks you are taking by doing so.

Posted by dorong | 3 comment(s)
תגים:, ,
More Posts Next page »