Getting Plug-In Path error while Downloading attac

2019-05-30 05:31发布

Business Process Error

System.ArgumentException: Illegal characters in path. at System.IO.Path.GetFileName(String path) at System.IO.File.InternalWriteAllBytes(String path, Byte[] bytes, Boolean checkHost)at RetrieveAttachments.RetrieveClass.Execute(IServiceProvider serviceProvider)

The code is as follows:

QueryExpression notes = new QueryExpression { EntityName = "annotation", ColumnSet = new ColumnSet("filename", "subject", "annotationid", "documentbody","mimetype") };
                    notes.Criteria.AddCondition("annotationid", ConditionOperator.Equal, annotationid);
                    EntityCollection NotesRetrieve = service.RetrieveMultiple(notes);
                    if (NotesRetrieve != null && NotesRetrieve.Entities.Count > 0)
                    {
                        foreach (var note in NotesRetrieve.Entities)
                        {
                        string fileName = note.GetAttributeValue<string>("filename");
                        //string fileType = note.GetAttributeValue<string>("mimetype");
                        FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.Write, "D:\\note");
                        string fileLocation = f+ fileName;
                        byte[] fileContent = Convert.FromBase64String(NotesRetrieve.Entities[0].Attributes["documentbody"].ToString());
                        System.IO.File.WriteAllBytes(fileLocation, fileContent); 
                        }

                     }
                   }
                  catch (Exception ex)
                   {
                    throw new InvalidPluginExecutionException(ex.ToString());
                   }

4条回答
冷血范
2楼-- · 2019-05-30 05:55

Santosh,

You can use following code to download attachments from Note entity in Dynamics CRM online.

code for .cs file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int choice;
            CrmServiceClient crmConn = new CrmServiceClient(ConfigurationManager.ConnectionStrings["CRM"].ConnectionString);
            IOrganizationService crmService = crmConn.OrganizationServiceProxy;
                    QueryExpression w_query = new QueryExpression { EntityName = "annotation", ColumnSet = new ColumnSet("filename","documentbody") };

                    EntityCollection w_account = crmService.RetrieveMultiple(w_query);
                     string name = "";
                    foreach (var count in w_account.Entities)
                    {
                        name = count.GetAttributeValue<string>("filename");

                        string doc_content = count.GetAttributeValue<string>("documentbody");
                        System.IO.FileStream wFile;
                        byte[] byteData = null;
                        if (name != null)
                        {
                            byte[] doc = Convert.FromBase64String(count.GetAttributeValue<string>("documentbody"));
                            byteData = doc;
                            wFile = new FileStream("D:\\attachments\\" + name, FileMode.Append);
                            wFile.Write(byteData, 0, byteData.Length);
                            wFile.Close();
                        }
                    }

                    Console.WriteLine("Please find all attachments in your local D: drive");
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadKey();

            }
        }

    }

Code for .config file:

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


  <connectionStrings>
    <add name="CRM" connectionString="AuthType=Office365;Url=https://your_organization_url; Username=your_user_name; Password=Your_password" />
  </connectionStrings>


    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.22.0.0" newVersion="2.22.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.22.0.0" newVersion="2.22.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

You just need to edit .config file code, this should work for you.

Note:you have to create C# console application and add required assemblies from Nuget.

查看更多
Fickle 薄情
3楼-- · 2019-05-30 06:06

This line is part of you culprit:

string fileLocation = f+ fileName;

This line is going to create an invalid file name because FileIOPermission.ToString() returns an XML fragment.

Here is an example to fix that issue, clean the filename of illegal characters, and use Path.Combine to build a valid file path.

string fileName = note.GetAttributeValue<string>("filename");
string cleanFileName = string.Empty;

    foreach (var chr in fileName.ToCharArray().ToList())
    {
        if (!Path.GetInvalidFileNameChars().Contains(chr)) cleanFileName = cleanFileName + chr; 
    }

FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.Write, @"D:\note");
string fileLocation = Path.Combine(@"D:\note", cleanFileName);
byte[] fileContent = Convert.FromBase64String(NotesRetrieve.Entities[0].Attributes["documentbody"].ToString());
System.IO.File.WriteAllBytes(fileLocation, fileContent);
查看更多
Evening l夕情丶
4楼-- · 2019-05-30 06:09

D:\note is a path of my machine where the file is downloaded.

If the above means you are trying to use a CRM plugin to write data to your local machine - as opposed to the CRM server - then this will never work.

The plugin runs on the CRM server so it wont have access to your client machine. E.g. when the plugin runs its looking for D:\note on the CRM server - not on your personal computer.

If you want to download files to your local machine you are better of creating a console application that runs on your local machine.

In any case there is an example of attachment downloading here. filePath in your case would be D:\note (this still won't work in a plugin though).

public void ExportDocuments(IOrganizationService service, String filePath)
{
     String fetch = @"<fetch mapping='logical' count='100' version='1.0'>
          <entity name='annotation'>
               <attribute name='filename' />
               <attribute name='documentbody' />
               <attribute name='mimetype' />
          </entity>
     </fetch>";

     foreach (Entity e in service.RetrieveMultiple(new FetchExpression(fetch)))
     {
          if (!String.IsNullOrWhiteSpace(e.Attributes["documentbody"].ToString()))
          {
               byte[] data = Convert.FromBase64String(e.Attributes["documentbody"].ToString());

               File.WriteAllBytes(filePath + e.Attributes["filename"].ToString(), data);
          }
     }
}
查看更多
狗以群分
5楼-- · 2019-05-30 06:11

CRM Online supports only Sandbox mode that means it isolates the code, You can't access outside environment in Sandbox mode which in your case is you local computer drive.

To achieve your goal you can create a console application as James Wood have said, that will write files into your local machine.

查看更多
登录 后发表回答