我的目标是使用AuthorizationFilter或DelegatingHandler对Web API请求进行身份验证.我想在几个地方寻找客户端ID和身份验证令牌,包括请求正文.起初看起来这很简单,我可以做这样的事情
var task = _message.Content.ReadAsAsync<Credentials>();
task.Wait();
if (task.Result != null)
{
// check if credentials are valid
}
Run Code Online (Sandbox Code Playgroud)
问题是HttpContent只能读一次.如果我在处理程序或过滤器中执行此操作,则在我的操作方法中无法使用该内容.我在StackOverflow上找到了一些答案,就像这样:在WebApi控制器中读取HttpContent,解释它是故意这样的,但是他们没有说明为什么.这似乎是一个非常严重的限制,阻止我在过滤器或处理程序中使用任何很酷的Web API内容解析代码.
这是技术限制吗?它是否试图阻止我做一件我没看到的非常糟糕的事情(?)?
死后:
我看了一下菲利普建议的来源.ReadAsStreamAsync返回内部流,如果流支持 Seek,则没有什么能阻止您调用Seek .在我的测试中,如果我调用ReadAsAsync,那么这样做:
message.Content.ReadAsStreamAsync().ContinueWith(t => t.Result.Seek(0, SeekOrigin.Begin)).Wait();
Run Code Online (Sandbox Code Playgroud)
当它触及我的动作方法时,自动模型绑定过程可以正常工作.我没有使用它,但我选择了更直接的东西:
var buffer = new MemoryStream(_message.Content.ReadAsByteArrayAsync().WaitFor());
var formatters = _message.GetConfiguration().Formatters;
var reader = formatters.FindReader(typeof(Credentials), _message.Content.Headers.ContentType);
var credentials = reader.ReadFromStreamAsync(typeof(Credentials), buffer, _message.Content, null).WaitFor() as Credentials;
Run Code Online (Sandbox Code Playgroud)
使用扩展方法(我在.NET 4.0中没有await关键字)
public static class TaskExtensions
{
public static T WaitFor<T>(this Task<T> task)
{
task.Wait();
if (task.IsCanceled) { throw …Run Code Online (Sandbox Code Playgroud) 当我在Visual Studio中实现一个事件时,Resharper非常友好地为我创建一个事件调用器.我通常在过去手工完成这个,而我的调用者总是这样
private void InvokePropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
Run Code Online (Sandbox Code Playgroud)
但是Resharper创建的调用器看起来像这样(用手清理一下)
private void InvokePropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler changed = PropertyChanged;
if (changed != null)
{
changed(this, e);
}
}
Run Code Online (Sandbox Code Playgroud)
在jetbrains的人们知道关于c#的事情我不知道吗?拥有局部变量是否有一些技术优势,或者只是它们必须自动生成代码的工件?
我的要求:
我有一个到目前为止似乎有效的解决方案,但我对此不太满意,并且认为我可能错过了一些东西。以下是我的测试应用程序中的 void Main:
var source = new CancellationTokenSource();
// Create an observable sequence for the Cancel event.
var cancelObservable = Observable.Create<Int64>(o =>
{
source.Token.Register(() =>
{
Console.WriteLine("Start on canceled handler.");
o.OnNext(1);
Console.WriteLine("End on canceled handler.");
});
return Disposable.Empty;
});
var observable =
// Create observable timer.
Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(10), Scheduler.Default)
// Merge with the cancel observable so we have a composite that
// …Run Code Online (Sandbox Code Playgroud)