Tuesday 11 February 2014

Error Type:The form cannot be submitted to the specified SharePoint list or document library. The SharePoint location may be read-only or you may not have permissions to access it.

I have recently working with InfoPath forms integration with SharePoint 2010 and got "The form cannot be submitted to the specified SharePoint list or document library. The SharePoint location may be read-only or you may not have permissions to access it."
 
Bug Source is :
 
There is one custom list and items are added through workflow and when anonymous user try to edit and while saving getting the error.

The root cause of that error is
 
Solution :
Modify the Item-Level Permission to allow all users to "Create and edit all items"-
Go to List Settings –> Advanced Settings
Change the "Item-Level Permissions" back to allow all users to "Create and edit all items" – this assumes you don't need item-level permissions on this list.

 

How to Programmatically Impersonate Users in SharePoint or How to run code Under administrator privileges in SharePoint

There are two ways to run a set of lines of code under administrator privileges.

Method 1:using runwithelivatedprevilages

this method runs under the Application Pool identity, which has site collection administrator privileges on all site collections hosted by that application pool.
NOTE: All the operations done inside this method should use a new SPSite Object. This means that the SPSite variables that are instantiated or created outside the subset code of this method can't be used for security elevation and it will result with the "Access denied error".

Wrong:

//SPSite Object created outside the RWEP Method
SPSite  site = new SPSite("siteURL");

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPWeb web = site.OpenWeb())
    {
        string user = web.CurrentUser.Name;
        //Operations that need high level access.
    } 

});

Correct:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    //New SPSite object.
     using (SPSite site = new SPSite(web.Site.ID))
     {
    //Do things by assuming the permission of the "system account".
     }
});

Remember that, don’t use an object created outside of the RunWithElevatedPrivileges delegate within the delegate, and dispose all SPSite and SPWeb objects created within the delegate before the delegate completes.
And also dont use SPContext.Current.Web; to get SPWeb reference within the RunWithElevatedPrivileges.


Method 2: Using SPUserToken

Alternative impersonation technique to RunWithElevatedPrivileges() method:

We can either create a new SPSite instance from the existing SPSite Object, whose constructor will be provided by the "UserToken" of the System Account or we can assign the "UserToken" property of the SPSite object, see the below code snippet.

//Creating a SPUsertoken object.
SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;
//passing to the constructor of the SPSite

SPSite spSite=new SPSite("siteURL",saUserToken);

or

SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;
SPSite spSite=new SPSite("siteURL");
//assigning the UserToken property of SpSite.

spSite.UserToken= saUserToken;  

Bellow is example for UserToken

SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;

using (var site3 = new SPSite(site.OpenWeb().Url, saUserToken ))
{
// This code runs under the security context of the SHAREPOINT system
//  for all objects accessed through the "site" reference. Note that it’s a
// different reference than SPContext.Current.Site.

   using (var elevatedWeb = site3.OpenWeb())
     {
       // Perform actions as SYSTEM here
       SPUser spUser = elevatedWeb.EnsureUser(username);
       SPGroup spGroup = elevatedWeb.SiteGroups["Partners"];
       if (spGroup != null)
        {
          site3.AllowUnsafeUpdates = true;
          spGroup.AddUser(spUser.ToString(), spUser.Email.ToString(),                                           spUser.Name.ToString(), spUser.Notes.ToString());
          site3.AllowUnsafeUpdates = false;
       }
    }
}

Login failed for user 'NT authority IUSR'. sharepoint 2010

If you have created an external content type and are trying to access it in a list and get "AccessDenied" then that is because you have not given permissions to the logged in user to use that external content type. You can easily give permissions to that user or to all users in your site by going to the Central Administration site and configuring the business connectivity service. For the exact procedure of how to do it read the following. 
To resolve this problem, either change the application pool identity or add "NT AUTHORITY\IUSR" to the database permissions. The first scenario is quite common. You can change application pool identity by going to the web server and updating the application pools or by logging into the SharePoint Central Administration site and going to" ManageService Accounts". We will cover the second scenario here; that is, to add IUSR to the database.

Steps:
1. Go to Microsoft SQL Server Management Studio and connect to your database server.
2. Expand the Security node and right-click the Logins node and select New Login.
Login-In-Database-Server.jpg
3. In the Login Name, enter IUSR and click "Search….". This will open a new search box. Enter "IUSR" in the object name and click "Check Names". Click "OK".
4. You will notice that the Login Name has been populated with "MACHINENAME\IUSR" where "MACHINENAME" is your machine name, for example, in the figure below, you see "SP2010\IUSR. SP2010" is my machine name.

This is not what you want to add to the logins. Change "MACHINENAME" to "NT AUTHORITY" so Login Name should read "NT AUTHORITY\IUSR". Click "OK".
6. To map the user to the database, right-click "NT AUTHORITY\IUSR" in Logins and select "Properties"
Map-User-to-Database.jpg
7. There are two ways to do this mapping. One way is to add the user to one of the server roles, for example,  server adminorsys admin. This will provide useful rights to all databases and thus you won't have to do explicit mapping. To do this, on the properties page, click ServerRoles and check sysadmin. Click "OK". Obviously you would not want to do this in a real environment. So the other option is to map the user directly to the database that has been used in the external content type.
Mapping-user-using-server-roles.jpg
To add a user mapping, in "LoginProperties", click "User Mapping". Locate the database in the list and then check the box in the Map column. As soon as you check the box, "NT AUTHORITY\IUSER" appears in the User column. That's it. Click OK to save the setting. By the way, on the same properties page, you can also assign database role membership to the user for the database but that is not required.
Mapping-User-Using-Login-Properties.jpg
Now, go back to the list page and reload it. You will see results from the external data source. Hope you enjoy this tutorial.