System.AccessViolationException'发生在Azure上的System.Net.Http.Formatting.dll中

时间:2014-12-17 13:09:58

标签: c# azure

我在这个问题上拔头发,我想知道是否有人可以提供帮助。

我试图创建一个POST和PUT http web api方法来处理JSON数据和图像数据。当使用Azure模拟器在我的本地计算机上运行时,这一切都很完美,但是一旦我发布到服务器,我就会收到一个AccessViolationException错误:

  

附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

我使用以下代码,在对Azure进行调试时,代码在读取多部分数据时失败。

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;
    }
}

正如我所说,这个代码在本地计算机上运行时效果很好,但在Azure上运行时则不行。

有什么想法吗?

由于

尼尔

1 个答案:

答案 0 :(得分:0)

我知道这是一篇较旧的文章,但我也有同样的例外,我希望对我有用的东西可以帮助其他人。就我而言,问题在于System.Net.Http的版本不匹配。这些是我为修复而采取的步骤。

  1. 删除对System.Net.Http的所有引用
  2. 从Nuget获取System.Net.Http
  3. 确保绑定位于我的app / web.config({version} = dll版本)中
<dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-{version}" newVersion="{version}" />
</dependentAssembly>

希望这会有所帮助!