4

I have used same instance of ClientContext inside a RemoteEventReceiver (MinRer.svc.cs) in a provider hosted app to get RootWeb, SubWebs, ListItems and I have added ListItems to lists. It works like a charm. However when I try to copy documents from the RootWeb into a SubWeb it generates 401 unauthorized error when it calls OpenBinaryDirect to get FileInformation FileInformation fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, myFile.ServerRelativeUrl);

I have now two questions. 1. Why it generates 401 error only when it invokes OpenBinaryDirect method and not all other methods regarding webs and lists? 2. I have solved this problem by adding credentials to the ClientContext. But I want to solve it without using username and password of a user in the code.following is my code:

var targetSite = new Uri(rootWeb.Url);
var login = "[email protected]";
var password = "MyPassword";
var securePassword = new System.Security.SecureString();
foreach (char c in password)
{
    securePassword.AppendChar(c);
}
ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties)
 var onlineCredentials = new SharePointOnlineCredentials(login, securePassword);
 clientContext.Credentials = onlineCredentials;
 FileInformation fileInfo = File.OpenBinaryDirect(clientContext, myFile.ServerRelativeUrl);

How do I solve this without using UserName and password in the code? thanks

OBS: This is a RemoteEventReceiver and I have no access to Page instance or Request.

OBS: The logged on user is same that its credentials added to the code.

5
  • What are the permissions for the app? You can create the context using the TokenHelper class. using ( ClientContext cc = TokenHelper.CreateRemoteEventReceiverClientContext( properties ) ) { }
    – wjervis
    May 2, 2014 at 12:50
  • Yes this is the same context which I have used to get RootWeb, SubWebs, lists and items. but it generates 401 when it calls OpenBinaryDirect. as I described I solved the problem by changing my code to the code I wrote in my question. and the app has SiteCollection and web permissions
    – Medes
    May 2, 2014 at 13:11
  • Can you show the code generating the error rather than the code that solved it?
    – wjervis
    May 2, 2014 at 18:06
  • It is same code I just added credentials to the context
    – Medes
    May 4, 2014 at 8:32
  • I think this is a duplicate question sharepoint.stackexchange.com/questions/70151/…
    – Hugh Wood
    May 12, 2014 at 8:27

2 Answers 2

4

I had the same issue and solved this the following way: You do not need to use "OpenBinaryDirect()" but simply OpenBinary(), which does not require an url and does not return a stream directly, but a ClientResult<Stream>.

(I retrieved the binary data and filename, reduce your code if you don't need both)

So you simple skip a step and end up using the following:

string base64 = null;
var streamX = file.OpenBinaryStream();
context.ExecuteQuery();
var stream = streamX.Value;

byte[] binaryfile = new byte[stream.Length];
stream.Read(binaryfile, 0, (int)stream.Length);
base64 = Convert.ToBase64String(binaryfile);
fileName = file.Name;
return base64;
0
1

This is how I save a file from a document library by Id. It's very dirty code, but as POC, it's enough :) Once I save the file, I just create a sytem.io.stream and load it up in a library I need.

   [SharePointContextFilter]
    [HttpGet]
    public ActionResult Read(int ShowDocId)        
    {


        List<DocumentLibListViewModel> listViewItems = new List<DocumentLibListViewModel>();
        var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

        using (var context = spContext.CreateUserClientContextForSPHost())
        {
            Web web = context.Web;

            List list = web.Lists.GetByTitle("Documents");

            CamlQuery caml = CamlQuery.CreateAllItemsQuery(100);
            ListItemCollection items = list.GetItems(caml);

            context.Load(items);
            context.ExecuteQuery();

            if (items != null)
            {
                foreach (var item in items)
                {
                    if (ShowDocId == item.Id)
                    {
                        string fileName = Guid.NewGuid().ToString();
                        var streamX = item.File.OpenBinaryStream();
                        context.ExecuteQuery();
                        var stream = streamX.Value;

                        byte[] binaryfile = new byte[stream.Length];
                        stream.Read(binaryfile, 0, (int)stream.Length);
                        var base64 = Convert.ToBase64String(binaryfile);

                        //save file to a folder
                        var savedUrl = HttpRuntime.AppDomainAppPath + "\\cache\\" + fileName;

                        System.IO.File.WriteAllBytes(savedUrl, Convert.FromBase64String(base64));



                        ViewBag.FileLocalUrl = savedUrl;
                    }
                }
            }


            return View();
        }

    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.