如何在MVC webApi控制器操作中读取PUT请求中的内容.
[HttpPut]
public HttpResponseMessage Put(int accountId, Contact contact)
{
var httpContent = Request.Content;
var asyncContent = httpContent.ReadAsStringAsync().Result;
...
Run Code Online (Sandbox Code Playgroud)
我在这里得到空字符串:(
我需要做的是:弄清楚在初始请求中修改/发送了什么属性(意味着如果Contact对象有10个属性,并且我只想更新其中2个属性,我只发送和对象只有两个属性,这样的事情:
{
"FirstName": null,
"LastName": null,
"id": 21
}
Run Code Online (Sandbox Code Playgroud)
预期的最终结果是
List<string> modified_properties = {"FirstName", "LastName"}
Run Code Online (Sandbox Code Playgroud) 在这种情况HttpApplication.BeginRequest下,我如何阅读整个原始请求体?当我尝试读取它时InputStream长度为0,这让我相信它可能已经被ASP.NET读过了.
我试过像这样读取InputStream:
using (StreamReader reader = new StreamReader(context.Request.InputStream))
{
string text = reader.ReadToEnd();
}
Run Code Online (Sandbox Code Playgroud)
但我得到的只是一个空字符串.我已经将位置重置为0,但当然一旦读取了它,它就会消失,所以这样做不起作用.最后,检查流的长度返回0.
编辑:这是针对POST请求的.
我有一个名为Log的属性,它尝试将请求和响应的内容记录到文本文件中.我把它放在我的控制器上以涵盖所有动作.在LogAttribute中,我正在将内容读取为字符串(ReadAsStringAsync),因此我不会丢失请求正文.
public class LogAttribute : ActionFilterAttribute
{
// ..
public override void OnActionExecuting(HttpActionContext actionContext)
{
// stuff goes here
var content = actionContext.Request.Content.ReadAsStringAsync().Result;
// content is always empty because request body is cleared
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
// other stuff goes here
var content = actionContext.Request.Content.ReadAsStringAsync().Result;
// content is always empty because request body is cleared
}
// ..
}
Run Code Online (Sandbox Code Playgroud)
另一方面,我在我的动作参数类之前放置了FromBody属性以利用它的好处.
[Log]
public class SomethingController
{
public HttpResponseMessage Foo([FromBody] myModel)
{
// something
}
}
Run Code Online (Sandbox Code Playgroud)
问题是ActionExecuting或ActionExecuted中的内容始终为空.
我认为这是因为FromBody在我的Log属性之前运行,而不像它们在代码中的顺序.我再次认为是因为根据动作参数(路径处理)找到了请求的最佳动作/控制器匹配.之后我的请求正文被清除,因为请求正文在WebApi中是非缓冲的. …
在Controller中的Action中尝试对象时,偶尔似乎是null.我发现,这是由于ReadAsStringAsync()在SendAsync()的覆盖DelegatingHandler.问题在于内容.当我的客户端发送一个内容正文并在记录器中读取它时,它永远不会被Controller Action Invoker读取(或者可能在某个地方JsonFormatter).我怀疑后续调用Content.ReadAsStringAsync()不会抛出异常,但也不会返回预期的内容体(返回一些信息表明异步读取已完成).
但是我的问题仍然存在,因为我想[FromBody]在一个动作中读取一个参数,当它Content.ReadStringAsync获得RaceCondition的时候它是null DelegatingHandler.当JsonFormatter虽然赢了,我得到的对象,但是这是罕见的(只在服务启动).
这是我的DelegatingHandler代码:
public class LogHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var apiRequest = new WebApiUsageRequest(request);
WriteLog(apiRequest);
request.Content.ReadAsStringAsync().ContinueWith(t =>
{
apiRequest.Content = t.Result;
WriteLog(apiRequest);
});
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var apiResponse = new WebApiUsageResponse(task.Result);
apiResponse.Content = task.Result.Content != null ? task.Result.Content.ReadAsStringAsync().Result : null;
WriteLog(apiResponse);
return task.Result;
});
}
}
Run Code Online (Sandbox Code Playgroud)
有没有人有解决这个问题的线索?
我为我的web api创建了一个ActionFilterAttribute以授权人员.通过RequestUri获取accessToken是可以的,但是我想在表单数据中发送它.在ActionFilterAttribute的onActionExecuting方法中读取Request.Content时,服务器始终具有空结果.我怎么解决这个问题?代码如下所示:
public class RequireAuthorization : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
actionContext.Request.Content.ReadAsStringAsync().ContinueWith((t) =>
{
try
{
//query will result in empty string
string query = t.Result;
string UserID = HttpUtility.ParseQueryString(query).Get("UserID");
string accessToken = HttpUtility.ParseQueryString(query).Get("AccessToken");
UserRepository repository = new UserRepository();
repository.IsTokenValid(Convert.ToInt32(UserID), accessToken);
}
catch (Exception ex)
{
var response = new HttpResponseMessage
{
Content =
new StringContent("This token is not valid, please refresh token or obtain valid token!"),
StatusCode = HttpStatusCode.Unauthorized
};
throw new HttpResponseException(response);
}
});
base.OnActionExecuting(actionContext); …Run Code Online (Sandbox Code Playgroud) 我有一个DelegatingHandler实现来记录请求/响应内容:
public class RequestAndResponseLoggerDelegatingHandler : DelegatingHandler
{
public IDataAccess Data { get; set; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var started = DateTime.UtcNow;
var response = await base.SendAsync(request, cancellationToken);
await Log(started, request, response);
return response;
}
private async Task Log(DateTime start, HttpRequestMessage request, HttpResponseMessage response)
{
var finished = DateTime.UtcNow;
var requestContent = await request.Content.ReadAsStringAsync();
var responseContent = await response.Content.ReadAsStringAsync();
var info = new ApiLogEntry(start, finished, requestContent, responseContent, request, response);
Data.Log(info);
}
}
Run Code Online (Sandbox Code Playgroud)
但出于某种原因requestContent,空洞来了. …
c# ×5
asp.net-mvc ×3
asp.net ×2
async-await ×1
c#-4.0 ×1
http ×1
httpcontent ×1
rest ×1
web-services ×1