Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Tuesday, October 10, 2017

SharePoint 2010 - How to check if group exists without exception

The SharePoint Server handles some things differently than you might know from standard C # programs.
I recently stumbled upon that I've tried to determine if a user group exists in SharePoint. I thought no problem and tried it with this code:

string nameOfGroupToCheck = "Test Group";
SPGroup group = spWeb.Groups[nameOfGroupToCheck];
if(group != null) {
   ...
}

I assumed that the variable group is null if the group is not present, but SharePoint throws an exception instead.
This does not happen with the following code snippet:

using System.Linq;
...
string nameOfGroupToCheck = "Test Group";
if (spWeb.Groups.OfType<SPGroup>().Where(g => g.Name == nameOfGroupToCheck).Count() > 0)
{
  ...
}

To get this code work correctly, you need to add the System.Linq namespace into your code.

By the way, this check also works with lists in SharePoint. You would only have to query the lists instead of the groups.


Wednesday, January 6, 2016

SharePoint 2010 - How to check if SPGroup exists

I've tried to check, if a SPGroup exists this way:

string nameOfGroupToCheck = "My SPGroup";
if(spWeb.Groups[nameOfGroupToCheck] != null)
{
...
}

...but this causes an exception, when the SPGroup is not existing.
Try this one:

string nameOfGroupToCheck = "My SPGroup";
if (spWeb.Groups.OfType<SPGroup>().Where(g => g.Name == nameOfGroupToCheck).Count() > 0)
{
...
}

Tuesday, November 24, 2015

SharePoint 2010 - Tutorial - Hiding Ribbon Items

Today I want to show you, how you can hide items from the ribbon bar.
We start as usual with an empty SharePoint project.
Add a new item to the project: User Control and give it a name (i.e. "RibbonControl.ascx").


Add the "Microsoft.Web.CommandUI.dll" reference from "c:\program files\common files\microsoft shared\web server extensions\14\isapi"-folder to your project.



Then open the code-behind file. In my case it is "RibbonControl.ascx.cs".


Add the following namespaces to your code:

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.Web.CommandUI;

Use the ribbon.TrimById() method to hide items in the ribbon bar.
Here are some examples. See a full list of all ribbon items here:

https://msdn.microsoft.com/en-us/library/office/ee537543(v=office.14).aspx

protected void Page_Load(object sender, EventArgs e)
{
            try
            {
                SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);
                using (SPSite site = SPContext.Current.Site)
                {
                    //"Documents"-tab
                    ribbon.TrimById("Ribbon.Documents.Copies");
                    ribbon.TrimById("Ribbon.Documents.Workflow");
                    ribbon.TrimById("Ribbon.Documents.Share");
                    ribbon.TrimById("Ribbon.Documents.Manage.ManagePermissions");
                    ribbon.TrimById("Ribbon.Documents.TagsAndNotes");

                    //"Library"-tab
                    ribbon.TrimById("Ribbon.Library.ViewFormat");
                    ribbon.TrimById("Ribbon.Library.Share");
                    ribbon.TrimById("Ribbon.Library.Datasheet");
                    ribbon.TrimById("Ribbon.Library.Actions");
                    ribbon.TrimById("Ribbon.Library.CustomizeLibrary");
                }
            }
            catch (Exception exp)
            {
                throw exp;
            }
}

Then your user control is ready now.
The next step is to add your user control whereever you need it, i.e. to your master page, page, web parts etc..
To deploy a custom master page, see my blog post http://me-and-my-sharepoint.blogspot.de/2015/11/sharepoint-2010-tutorial-deploying.html
You can also use SharePoint Designer to modify a page.

I deployed a custom master page to hide ribbon items in all document libraries in a site collection.
Register the user control at the top of the page:

<%@ Register TagPrefix="custom" TagName="RibbonBarControl" src="~/_controltemplates/TestRibbonsHideProject/RibbonControl.ascx" %>




We've created user control for SharePoint 2010, registered it on the page. Now, the final step is to  include the user control in the page itself:


<custom:RibbonControl id="RibbonControl1" runat="server"></custom:RibbonControl>



Then we are ready to deploy the solution.

See the ribbon bar before activating our user control:



Then afterwards:



Hope you enjoyed it. Feel free to leave a comment, if you like (or not) ;-)

Tuesday, April 28, 2015

C# - using "params" in method parameter


You can define a method with "params":

void Method(string s, params object[] param)

That means, you can use this code to add parameters to the method 

Customer customer;
Method("bla", customer.CustomerID, customer.CustomerSearchName);

instead of defining this:

void MethodKacke(string s, object[] param)

Then the method parameters had to  be like this:


MethodKacke("bla", new object[] { customer.CustomerID, customer.CustomerSearchName });

So using params is the more easy way. :-)

Wednesday, March 4, 2015

C# - How to implement the IList Interface into a collection class

Yesterday I learned how to implement interfaces into my classes. 
I will show you, how to implement the IList interface into my custom collection class.
It's very simple. :-)

First we have to add 2 references to your class:

using System.Collections.Generic;
using System.Collections;
Then you have to add the interface behind your class name:

namespace MyProject.Classes
{
    class CollectionBase<T> : Connection, IList<T>
...

My example code is a universal collection class. Therefore, there is the type not defined of the IList not defined. You could write instead IList<MyClass>.

After added the interface name to the class, we can use the Visual Studio feature "Implement Interface":






The following code will be added automatically:

public int IndexOf(T item)
{
throw new NotImplementedException();
}

public void Insert(int index, T item)
{
throw new NotImplementedException();
}

public void RemoveAt(int index)
{
throw new NotImplementedException();
}

public T this[int index]
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}

public void Add(T item)
{
throw new NotImplementedException();
}

public void Clear()
{
throw new NotImplementedException();
}

public bool Contains(T item)
{
throw new NotImplementedException();
}

public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}

public int Count
{
get { throw new NotImplementedException(); }
}

public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}

public bool Remove(T item)
{
throw new NotImplementedException();
}

public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}

IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}

Now we have all methods declared, but not defined yet.
We add now a list of our class to store to code:

#region Variables
private List<T> _InternalList = new List<T>();
#endregion

This list we can use to store all objects from the given class.

Now we have to modify the methods:

public int IndexOf(T item)
{
return _InternalList.IndexOf(item);
}

public void Insert(int index, T item)
{
_InternalList.Insert(index, item);
}

public void RemoveAt(int index)
{
_InternalList.RemoveAt(index);
}

public T this[int index]
{
get
{
        return _InternalList[index];
}
set
{
_InternalList[index] = value;
}
}

public void Add(T item)
{
_InternalList.Add(item);
}

public void Clear()
{
_InternalList.Clear();
}

public bool Contains(T item)
{
return _InternalList.Contains(item);
}

public void CopyTo(T[] array, int arrayIndex)
{
_InternalList.CopyTo(array, arrayIndex);
}

public int Count
{
get 
{
return _InternalList.Count;
}
}

public bool IsReadOnly
{
get 
{
return false;
}
}

public bool Remove(T item)
{
return _InternalList.Remove(item);
}

public IEnumerator<T> GetEnumerator()
{
return _InternalList.GetEnumerator();
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return (IEnumerator)this;
}

Now we have the interface implemented and are able to use the collection.

Here is the complete code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MyProject.Classes
{
    class CollectionBase<T> : Connection, IList<T>
    {
        #region Variables
        private List<T> _InternalList = new List<T>();
        #endregion

        #region Properties
        #endregion

        #region Constructors
        public CollectionBase()
        {
        }
        #endregion

        #region Methods
        #endregion

        #region IList Interface
        public int IndexOf(T item)
        {
            return _InternalList.IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            _InternalList.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            _InternalList.RemoveAt(index);
        }

        public T this[int index]
        {
            get
            {
                return _InternalList[index];
            }
            set
            {
                _InternalList[index] = value;
            }
        }

        public void Add(T item)
        {
            _InternalList.Add(item);
        }

        public void Clear()
        {
            _InternalList.Clear();
        }

        public bool Contains(T item)
        {
            return _InternalList.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            _InternalList.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get 
            {
                return _InternalList.Count;
            }
        }

        public bool IsReadOnly
        {
            get 
            {
                return false;
            }
        }

        public bool Remove(T item)
        {
            return _InternalList.Remove(item);
        }

        public IEnumerator<T> GetEnumerator()
        {
            return _InternalList.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (IEnumerator)this;
        }
        #endregion
    }
}

Monday, November 3, 2014

C# - Null-coalescing Operator



The "??" operator is called the null-coalescing operator and is used to define a default value for a nullable value types as well as reference types. It returns the left-hand operand if it is not null; otherwise it returns the right operand.


Example:

int? a = 123;
int? b = 5;
int? x = a ?? b;

/*Output:x = 123*/



int? a = null;
int? b = 5;
int? x = a ?? b;

/*Output:x = 5*/

Friday, June 13, 2014

SharePoint 2010 - Building Custom Actions in Visual Studio

Today I will show how you can add custom actions to the ribbon bar and the edit control block in SharePoint.

We have to start with creating an empty element in the project. Then replace the text in the xml file with this:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
  Description="Approve Documents"
  Title="Approve Documents"
  Id="RibbonDocumentsManageApproveDocuments"
  Location="CommandUI.Ribbon"
  RegistrationId="10000"
  RegistrationType="List"
  Sequence="0"
  xmlns="http://schemas.microsoft.com/sharepoint/">
    <CommandUIExtension xmlns="http://schemas.microsoft.com/sharepoint/">
      <!-- Define the (UI) button to be used for this custom action -->
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.Documents.Manage.ApproveDocuments"
          Command="{4E2F5DC0-FE2C-4466-BB2D-3ED0D1917763}"
          Image32by32="~site/_layouts/Images/SharePoint-Z-Drive-Project/approve_document_32x32.png"
          Image16by16="~site/_layouts/Images/SharePoint-Z-Drive-Project/approve_document_16x16.png"
          Sequence="0"
          LabelText="Approve Documents"
          Description="Approve Documents"
          TemplateAlias="o1" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <!-- Define the action expected on the button click -->
        <CommandUIHandler Command="{4E2F5DC0-FE2C-4466-BB2D-3ED0D1917763}" CommandAction="javascript:window.open('http://www.bing.com/search?q='.concat(escape(document.title)))" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>

  <CustomAction
  Description="Approve Document"
  Title="Approve Document"
  Id="EditControlBlockApproveDocument"
  Location="EditControlBlock"
  RegistrationId="10000"
  RegistrationType="List"
  ImageUrl="~site/_layouts/Images/SharePoint-Z-Drive-Project/approve_document_16x16.png"
  Sequence="1101"
  xmlns="http://schemas.microsoft.com/sharepoint/">
    <CommandUIExtension xmlns="http://schemas.microsoft.com/sharepoint/">
      <!-- Define the (UI) button to be used for this custom action -->
      <CommandUIDefinitions>
        <CommandUIDefinition Location="EditControlBlock">
          <Button Id="EditControlBlock.ApproveDocument"
          Command="{F8C45D3A-A00D-4412-91BB-C49D75A36F3A}"
          Sequence="1101"
          LabelText="Approve Document"
          Description="Approve Document"
          TemplateAlias="o2" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <!-- Define the action expected on the button click -->
        <CommandUIHandler Command="{F8C45D3A-A00D-4412-91BB-C49D75A36F3A}" CommandAction="javascript:window.open('http://www.bing.com/')" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

The first custom action is to add the button to ribbon bar in the document library. 
The second custom action will add the button to the edit control block of an item.

Wednesday, June 11, 2014

SharePoint 2010 - Tutorial - Create an event receiver with custom error message on redirect url while item updating

Today I would like to show you, how you can use event receivers to check documents / items in a list and give the user immediately a feeback about an error, while he is still in the edit form of the item / document.
That can be useful for users, because they don't leave the edit form and can correct the error immediately without opening the edit mask again.
We start with an empty SharePoint Project in Visual Studio 2010.


Set a project name ("SPProject"), then provide the url and set the trust level ("Farm solution").


The first step is to add the list definition with list instance to our project. That will be our list, where the event receiver will be listen on. Right-click the project name in the project explorer and choose "Add" -> "New Item".


From the list select "List Defintion" and set a name for it ("ListDefinition"), then press "Add".


On the next screen you have to enter a name for the list definition ("SPProject - ListDefinition"). Also you have to choose, which type the list should be. In my case it was a document library, but you can use other types as well. Ensure that the box "Add a list instance for the list definition" is ticked.


After we have added the list defintion, we can add our event receiver. The event receiver will check our doucment and return an error to the edit form, when the item / document is not ok. So we right-click again on the project name in the project explorer and choose "Add" -> "New Item" again.


Now we choose "Event Receiver" from the list and set again a name ("EventReceiver").


On the next screen, we have to decide, which type of event receiver we would like to have. We want the event receiver to check the items of a list - so our choice is "List Item Events".
Then we have to tell SharePoint on which list the event receiver should listen. That is our created list instance from our list definition ("SPProject - ListDefinition").
The last point we have to decide, when the event receiver should start its work. We select "An item is being added".


In the file "EventReceiver.cs" we can add now our code, our logic to check the item / document.
I keep it simple for this example. I will only check if the title property starts with the word "SharePoint", otherwise I want to give an error message to the user. You can put in there more complex logic according to your needs.
Open the "EventReceiver.cs" and search for the method "ItemUpdating". Overwrite the method with your code:

/// <summary>
/// An item is being updated.
/// </summary>
public override void ItemUpdating(SPItemEventProperties properties)
{
  try
  {
    base.ItemUpdating(properties);
    // ensure that the code will be executed only once
    if ((properties.AfterProperties["vti_sourcecontrolcheckedoutby"] == null && properties.BeforeProperties["vti_sourcecontrolcheckedoutby"] != null) || (properties.AfterProperties["vti_sourcecontrolcheckedoutby"] == null && properties.BeforeProperties["vti_sourcecontrolcheckedoutby"] == null))
    {
      // check title property
      if (properties.AfterProperties["vti_title"].ToString().StartsWith("SharePoint") == false)
      {
        // redirect
        properties.RedirectUrl = @"EditForm.aspx?"
                                 + "Mode=Upload"
                                 + "&CheckInComment="
                                 + "&ID=" + properties.ListItem.ID
                                 + "&RootFolder=%2Fsites%2FIT%2FLists%2FSPProject-ListInstance1"
                                 + "&IsDlg=1"
                                 + "&ContentTypeId=" + properties.ListItem.ContentType.Id
                                 + "&IsDlg=1";
        properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
       }
      }
     }
     catch (Exception exp)
     {
       throw exp;
     }
 
}
I use the property "vti_sourcecontrolcheckedoutby" to ensure that the code is executed once and nor multiple times. If you have enabled versioning in your list, the event will be fired muliple.
Then I use the AfterProperties to check the title. If the check fails, SharePoint should redirect the user to a specific url. We set the url to our editform.aspx of the list. 
Note: You have to check the bold marked area in the code (RootFolder parameter). You have to change this to your list url!

Now we can start the solution. Navigate to the list, add an item and edit the properties afterwards. You will see that the title have to start with the word "SharePoint", otherwise the popup comes up again when saving.


But we still have no error displayed to the user. The user would be confused now, because he don't knows what is wrong and why he cannot save the properties.

To display an error on the editform.aspx of the list, we create a simple visual webpart.
We add another item to our project via right-click on the project name in the project explorer.


Select "Visual WebPart" from the list and set a name ("VisualWebPart").


To the visual webpart we add just a label ("Label1") from the toolbox ("VisualWebPartUserControl.ascx").


In my solution I did some small changes to the label, like red color, another font, cleared the text property of the label etc, but this is up to you, how you design the label.

Now we open the code-behind file "VisualWebPartUserControl.ascx.cs" and modify the Page_Load method.

protected void Page_Load(object sender, EventArgs e)
{
  string ErrorMessage = System.Web.HttpUtility.ParseQueryString(System.Web.HttpContext.Current.Request.Url.Query).Get("error");
  this.Label1.Text = ErrorMessage;
}

Explanation:
We use the HttpUtility class to get the parameter "error" from the current url. The paramter "error" we will use later for our custom error message.
The content of the error parameter we put in our label text property.

Now we have our webpart for displaying the error message, but we still have to put in the editform.aspx of our list.
Therefore we open the file "schema.xml" of our list definition and search for the "<Forms>" section in it.
It should similar look like this:


Now we create our custom editform.aspx by creating a new <Form> from type "EditForm". Give a own name ("MyEditForm.aspx") and set default = true:


Code:
      <Form Type="EditForm"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main"
            Url="Forms/MyEditForm.aspx"
            Default="TRUE">
        <WebParts>
          <AllUsersWebPart WebPartZoneID="Main" WebPartOrder="0">
            <![CDATA[
            ]]>
          </AllUsersWebPart>
        </WebParts>
      </Form>

Now we have a custom editform.aspx, but we still have to put our webpart in it. Actually we have the same editform as the standard one. Open the file "VisualWebPart.webpart" from the project explorer.


Copy the complete code except the first line ("<?xml version....>) and paste it in the CDATA area in the schema.xml.
Your form code in your schema.xml should look like this now:


Code:
 <Form Type="EditForm"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main"
            Url="Forms/MyEditForm.aspx"
            Default="TRUE">
        <WebParts>
          <AllUsersWebPart WebPartZoneID="Main" WebPartOrder="0">
            <![CDATA[
            <webParts>
            <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
              <metaData>
                <type name="SPProject.VisualWebPart.VisualWebPart, $SharePoint.Project.AssemblyFullName$" />
                <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
              </metaData>
              <data>
                <properties>
                  <property name="Title" type="string">VisualWebPart</property>
                  <property name="Description" type="string">My Visual WebPart</property>
                </properties>
              </data>
            </webPart>
          </webParts>
            ]]>
          </AllUsersWebPart>
        </WebParts>
      </Form>

Now we have embedded the webpart in our custom editform.aspx.
We have to tell the event receiver, that it should redirect to our new custom editform.aspx ("MyEditForm.aspx") and we have to add the error parameter to our url.
Navigate back to the event receiver code file ("EventReceiver.cs") and modify the redirect url:

properties.RedirectUrl = @"MyEditForm.aspx?"
                         + "Mode=Upload"
                         + "&CheckInComment="
                         + "&ID=" + properties.ListItem.ID
                         + "&RootFolder=%2Fsites%2FIT%2FLists%2FSPProject-ListInstance1"
                         + "&IsDlg=1"
                         + "&ContentTypeId=" + properties.ListItem.ContentType.Id
                         + "&IsDlg=1"
                         + "&error=Error in Title - Must start with SharePoint";

Changes in code are marked in bold.
We changed the aspx file from "EditForm.aspx" to "MyEditForm.aspx" and added the parameter "error" with a custom error message.


Let's start the solution now. Navigate to the list, add an item and edit the properties afterwards. Click "Save" with an empty title. Now you should get the error message:


If you enter a text beginning with the word "SharePoint" in the title property the popup will disappear.
Hope you enjoyed this lesson. :-)

Sunday, June 8, 2014

SharePoint 2010 - Adding your created visual web part to the schema.xml of a list definition

Hi guys,

Today I tried to add a visual webpart to a list definition, especially to an indidividual edit form of the list definition.
I created a visual webpart in visual studio and a list definition with a list instance.
For the list defintion, I wanted to add a custom editform.aspx in the <forms> area of the schema.xml.
That can be done this way:

Find the <forms> area in the schema.xml:

    <Forms>
      <Form Type="DisplayForm" SetupPath="pages\form.aspx" Url="Forms/DispForm.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" SetupPath="pages\form.aspx" Url="Forms/EditForm.aspx" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="Forms/Upload.aspx" WebPartZoneID="Main" />
...

We see the 3 standard forms (display, edit and new). Now we can add a custom editform.aspx by defining a new form with the type "editform":

      <Form Type="EditForm"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main"
            Url="Forms/MyEditForm.aspx"
            Default="TRUE"></Form>

Important are the "type", "url" and the "default" property. The type as the name says, defines the type of the form. The url property can be defined free. You can enter there any name. And the last property "default", if this form will be the standard / default for the specific type.

If we start our solution now, we would have the same result as the standard editform.aspx. There would be no difference for the user. We, of course, can see that the url is different than the standard editform.aspx.

Now we want to add another webpart to our new editform.aspx (in my case myeditform.aspx):
First we have to add a container for all webparts, we want to add to the myeditform.aspx. This code has to placed between the <form> tags:

<Form Type="EditForm"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main"
            Url="Forms/MyEditForm.aspx"
            Default="TRUE">
        <WebParts>

        </WebParts>
</Form>

Then we need to add the webpart itself:

<Form Type="EditForm"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main"
            Url="Forms/MyEditForm.aspx"
            Default="TRUE">
        <WebParts>
          <AllUsersWebPart WebPartZoneID="Main" WebPartOrder="1">
            <![CDATA[

            ]]>
          </AllUsersWebPart>
        </WebParts>
</Form>

In the cdata area we can copy the complete code of our visual webpart file (*.webpart) except the first line:

<?xml version="1.0" encoding="utf-8"?>

So we get this result in the end:

<Form Type="EditForm"
            SetupPath="pages\form.aspx"
            WebPartZoneID="Main"
            Url="Forms/MyEditForm.aspx"
            Default="TRUE">
        <WebParts>
          <AllUsersWebPart WebPartZoneID="Main" WebPartOrder="1">
            <![CDATA[
<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <type name="SharePoint_Z_Drive_Project.WP_ErrorField.WP_ErrorField, $SharePoint.Project.AssemblyFullName$" />
      <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Title" type="string">Error</property>
        <property name="Description" type="string">Error Field WebPart</property>
      </properties>
    </data>
  </webPart>
</webParts>
            ]]>
          </AllUsersWebPart>
        </WebParts>
</Form>

If we start the solution now and edit an item in our list instance, we see the properties of our item and our visual webpart.