tl; dr 将两个数据(最多1MBish)从WPF应用程序传递到WebAPI服务方法的最佳方法是什么?
我目前正在尝试将二进制数据从WPF应用程序传递到WebAPI Web服务,并且结果可变。小文件(< 100k)通常可以正常工作,但任何更大的成功几率都会降低。
标准OpenFileDialog
,然后File.ReadAllBytes
将byte []参数传递给WPF中的客户端方法。这总是成功的,然后我通过PostAsync
调用和ByteArrayContent
参数将数据发布到WebAPI。
这是正确的方法吗?我开始使用PostJSONAsync调用,并将byte []传递给它,但认为ByteArrayContent看起来更合适,但都不能可靠地工作。
WPF中的客户端方法
public static async Task<bool> UploadFirmwareMCU(int productTestId, byte[] mcuFirmware)
{
string url = string.Format("productTest/{0}/mcuFirmware", productTestId);
ByteArrayContent bytesContent = new ByteArrayContent(mcuFirmware);
HttpResponseMessage response = await GetClient().PostAsync(url, bytesContent);
....
}
WebAPI方法
[HttpPost]
[Route("api/productTest/{productTestId}/mcuFirmware")]
public async Task<bool> UploadMcuFirmware(int productTestId)
{
bool result = false;
try
{
Byte[] mcuFirmwareBytes = await Request.Content.ReadAsByteArrayAsync();
....
}
网络配置设置
AFAIK web.config中的这些限制应该足以允许1MB文件到服务吗?
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
<httpRuntime targetFramework="4.5" maxRequestLength="2097152"/>
调用ReadAsByteArrayAsync()
时,我在WebAPI中收到错误。这些情况各不相同,可能是由于IIS Express中的应用程序池崩溃/进入了糟糕的状态,但它们包括以下内容(其中没有一个通过谷歌导致任何有希望的潜在客户):
Specified argument was out of the range of valid values. Parameter name: offset
at System.Web.HttpInputStream.Seek(Int64 offset, SeekOrigin origin)\r\n
at System.Web.HttpInputStream.set_Position(Int64 value)\r\n at System.Web.Http.WebHost.SeekableBufferedRequestStream.SwapToSeekableStream()\r\n at System.Web.Http.WebHost.Seek
OR
Message = "An error occurred while communicating with the remote host. The error code is 0x800703E5."
InnerException = {"Overlapped I/O operation is in progress. (Exception from HRESULT: 0x800703E5)"}
at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)\r\n
at System.Web.Hosting.IIS7WorkerRequest.ReadEntityCoreSync(Byte[] buffer, Int32 offset, Int32 size)\r\n
at System.Web.Hosting.IIS7WorkerRequ...
最初我认为这很可能取决于IIS Express的限制(在我的开发人员的Windows 7上运行)但我们在运行Server 2012的登台服务器上遇到了同样的问题。
任何有关如何使其工作的建议都会很棒,甚至只是从WPF上传文件到WebAPI的基本示例都会很棒,因为我发现的大部分代码都与上传文件有关来自多部分表格网页。
非常感谢您的任何帮助。
答案 0 :(得分:0)
tl; dr 这是WebApi服务中我们代码的一个独立部分导致它出错,呃!
啊,好吧,这很令人尴尬。事实证明我们的问题归结为我们在WebApiConfig.Register(HttpConfiguration config)
注册的请求记录器类,而且我已经忘记了。
它通过async作为StringContent读取请求内容,然后尝试将其记录到ncarchar(max)字段中的数据库。这本身可能没问题,但我猜测当LoggingHandler以及主WebApi控制器都试图通过异步访问请求内容时,所有奇怪的问题都会发生?
删除LoggingHandler会立即修复问题,我们现在可以上传最高100MB的文件而不会出现任何问题。为了更加永久地修复它,我想我需要重写LoggingHandler来设置对它尝试记录/忽略某些内容类型的最大内容大小的限制。
令人怀疑,但我希望有一天这对某人有用!
public class LoggingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
LogRequest(request);
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var response = task.Result;
// ToDo: Decide if/when we need to log responses
// LogResponse(response);
return response;
}, cancellationToken);
}
private void LogRequest(HttpRequestMessage request)
{
(request.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x =>
{
try
{
var callerId = CallerId(request);
var callerName = CallerName(request);
// Log request
LogEntry logEntry = new LogEntry
{
TimeStamp = DateTime.Now,
HttpVerb = request.Method.ToString(),
Uri = request.RequestUri.ToString(),
CorrelationId = request.GetCorrelationId(),
CallerId = callerId,
CallerName = callerName,
Controller = ControllerName(request),
Header = request.Headers.ToString(),
Body = x.Result
};
...........