2

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 = "MyNameh@MyDomain.onmicrosoft.com";
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.

  • 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 '14 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 '14 at 13:11
  • Can you show the code generating the error rather than the code that solved it? – wjervis May 2 '14 at 18:06
  • It is same code I just added credentials to the context – Medes May 4 '14 at 8:32
  • I think this is a duplicate question sharepoint.stackexchange.com/questions/70151/… – Hugh Wood May 12 '14 at 8:27
3

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

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, privacy policy and cookie policy

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