简体   繁体   中英

System.AccessViolationException' occurred in System.Net.Http.Formatting.dll on Azure

I'm pulling my hair out over this problem, I'm wondering if anyone can help.

I'm attempting to create a POST and PUT http web api method to handle both JSON data and image data. This all works perfectly when running on my local machine using the Azure emulator but as soon as I publish to the server I get an AccessViolationException error saying:

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

I'm using the following code and when debugging against Azure the code fails when reading the multipart data.

public async Task<bool> BindModelTask(HttpActionContext actionContext, System.Web.Http.ModelBinding.ModelBindingContext bindingContext) {
        try {
            if (actionContext.Request.Content.IsMimeMultipartContent()) {
                var provider = await actionContext.Request.Content.ReadAsMultipartAsync<InMemoryMultipartFormDataStreamProvider>(new InMemoryMultipartFormDataStreamProvider());

                FormCollection formData = provider.FormData;
                FileData[] fileData = provider.GetFiles().Result;

                if (formData != null && formData.Count == 1) {
                    Pet pet = (Pet)Newtonsoft.Json.JsonConvert.DeserializeObject(formData[0], typeof(Pet));

                    if (pet != null) {
                        petModel petModel = new petModel(pet);
                        if (fileData != null) {
                            petModel.file = fileData.FirstOrDefault();
                        }

                        bindingContext.Model = petModel;
                    }
                }
                return true;
            }
        }
        catch (Exception ex) { throw ex; }
    }
}


public class InMemoryMultipartFormDataStreamProvider : MultipartStreamProvider {
    private FormCollection _formData = new FormCollection();
    private List<HttpContent> _fileContents = new List<HttpContent>();

    // Set of indexes of which HttpContents we designate as form data
    private Collection<bool> _isFormData = new Collection<bool>();

    /// <summary>
    /// Gets a <see cref="NameValueCollection"/> of form data passed as part of the multipart form data.
    /// </summary>
    public FormCollection FormData {
        get { return _formData; }
    }

    /// <summary>
    /// Gets list of <see cref="HttpContent"/>s which contain uploaded files as in-memory representation.
    /// </summary>
    public List<HttpContent> Files {
        get { return _fileContents; }
    }

    /// <summary>
    /// Convert list of HttpContent items to FileData class task
    /// </summary>
    /// <returns></returns>
    public async Task<FileData[]> GetFiles() {
        return await Task.WhenAll(Files.Select(f => FileData.ReadFile(f)));
    }

    public override Stream GetStream(HttpContent parent, HttpContentHeaders headers) {
        // For form data, Content-Disposition header is a requirement
        ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
        if (contentDisposition != null) {
            // We will post process this as form data
            _isFormData.Add(String.IsNullOrEmpty(contentDisposition.FileName));

            return new MemoryStream();
        }

        // If no Content-Disposition header was present.
        throw new InvalidOperationException(string.Format("Did not find required '{0}' header field in MIME multipart body part..", "Content-Disposition"));
    }

    /// <summary>
    /// Read the non-file contents as form data.
    /// </summary>
    /// <returns></returns>
    public override async Task ExecutePostProcessingAsync() {
        // Find instances of non-file HttpContents and read them asynchronously
        // to get the string content and then add that as form data
        CloudBlobContainer _container = StorageHelper.GetStorageContainer(StorageHelper.StorageContainer.Temp);

        for (int index = 0; index < Contents.Count; index++) {
            if (_isFormData[index]) {
                HttpContent formContent = Contents[index];
                // Extract name from Content-Disposition header. We know from earlier that the header is present.
                ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
                string formFieldName = UnquoteToken(contentDisposition.Name) ?? String.Empty;

                // Read the contents as string data and add to form data
                string formFieldValue = await formContent.ReadAsStringAsync();
                FormData.Add(formFieldName, formFieldValue);
            }
            else {
                _fileContents.Add(Contents[index]);
            }
        }
    }

    /// <summary>
    /// Remove bounding quotes on a token if present
    /// </summary>
    /// <param name="token">Token to unquote.</param>
    /// <returns>Unquoted token.</returns>
    private static string UnquoteToken(string token) {
        if (String.IsNullOrWhiteSpace(token)) {
            return token;
        }

        if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1) {
            return token.Substring(1, token.Length - 2);
        }

        return token;
    }
}

As I said this code works perfectly when running on my local machine but not when running on Azure.

Any ideas?

Thanks

Neil

I know this is an older post but I had the same exception and I'm hoping that what worked for me can maybe help someone else. In my case the problem was with a version mismatch of System.Net.Http. These are the steps that I took for the fix.

  1. Remove all References to System.Net.Http
  2. Get System.Net.Http from Nuget
  3. Ensure that binding is in my app/web.config ({version} = dll version)
 <dependentAssembly> <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-{version}" newVersion="{version}" /> </dependentAssembly> 

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM