255 lines
7.7 KiB
C#
255 lines
7.7 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.Filters;
|
|
|
|
namespace BasicWebSite.Controllers
|
|
{
|
|
public class AsyncActionsController : Controller
|
|
{
|
|
const int SimulateDelayMilliseconds = 20;
|
|
|
|
public override void OnActionExecuted(ActionExecutedContext context)
|
|
{
|
|
// So that tests can observe we're following the proper flow after an exception, surface a
|
|
// message saying what the exception was.
|
|
if (context.Exception != null)
|
|
{
|
|
context.Result = Content($"Action exception message: {context.Exception.Message}");
|
|
context.ExceptionHandled = true;
|
|
}
|
|
}
|
|
|
|
public async void AsyncVoidAction()
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
}
|
|
|
|
public Task TaskAction()
|
|
{
|
|
return Task.Delay(SimulateDelayMilliseconds);
|
|
}
|
|
|
|
public async Task TaskExceptionAction()
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
throw new CustomException();
|
|
}
|
|
|
|
public async Task<Message> TaskOfObjectAction(string message)
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
return new Message { Text = message };
|
|
}
|
|
|
|
public async Task<Message> TaskOfObjectExceptionAction(string message)
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
throw new CustomException();
|
|
}
|
|
|
|
public async Task<IActionResult> TaskOfIActionResultAction(string message)
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
return Content(message);
|
|
}
|
|
|
|
public async Task<IActionResult> TaskOfIActionResultExceptionAction(string message)
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
throw new CustomException();
|
|
}
|
|
|
|
public async Task<ContentResult> TaskOfContentResultAction(string message)
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
return Content(message);
|
|
}
|
|
|
|
public async Task<ContentResult> TaskOfContentResultExceptionAction(string message)
|
|
{
|
|
await Task.Delay(SimulateDelayMilliseconds);
|
|
throw new CustomException();
|
|
}
|
|
|
|
public ValueTask<Message> PreCompletedValueTaskOfObjectAction(string message)
|
|
{
|
|
return new ValueTask<Message>(new Message { Text = message });
|
|
}
|
|
|
|
public ValueTask<Message> PreCompletedValueTaskOfObjectExceptionAction(string message)
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public ValueTask<IActionResult> PreCompletedValueTaskOfIActionResultAction(string message)
|
|
{
|
|
return new ValueTask<IActionResult>(Content(message));
|
|
}
|
|
|
|
public ValueTask<IActionResult> PreCompletedValueTaskOfIActionResultExceptionAction(string message)
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public ValueTask<ContentResult> PreCompletedValueTaskOfContentResultAction(string message)
|
|
{
|
|
return new ValueTask<ContentResult>(Content(message));
|
|
}
|
|
|
|
public ValueTask<ContentResult> PreCompletedValueTaskOfContentResultExceptionAction(string message)
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public CustomAwaitable CustomAwaitableVoidAction()
|
|
{
|
|
return new CustomAwaitable(SimulateDelayMilliseconds);
|
|
}
|
|
|
|
public CustomAwaitable CustomAwaitableVoidExceptionAction()
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public CustomAwaitable<Message> CustomAwaitableOfObjectAction(string message)
|
|
{
|
|
return new CustomAwaitable<Message>(
|
|
SimulateDelayMilliseconds,
|
|
new Message { Text = message });
|
|
}
|
|
|
|
public CustomAwaitable<Message> CustomAwaitableOfObjectExceptionAction(string message)
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public CustomAwaitable<IActionResult> CustomAwaitableOfIActionResultAction(string message)
|
|
{
|
|
return new CustomAwaitable<IActionResult>(SimulateDelayMilliseconds, Content(message));
|
|
}
|
|
|
|
public CustomAwaitable<IActionResult> CustomAwaitableOfIActionResultExceptionAction(string message)
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public CustomAwaitable<ContentResult> CustomAwaitableOfContentResultAction(string message)
|
|
{
|
|
return new CustomAwaitable<ContentResult>(SimulateDelayMilliseconds, Content(message));
|
|
}
|
|
|
|
public CustomAwaitable<ContentResult> CustomAwaitableOfContentResultExceptionAction(string message)
|
|
{
|
|
throw new CustomException();
|
|
}
|
|
|
|
public class Message
|
|
{
|
|
public string Text { get; set; }
|
|
}
|
|
|
|
public class CustomAwaitable
|
|
{
|
|
protected readonly int _simulateDelayMilliseconds;
|
|
|
|
public CustomAwaitable(int simulateDelayMilliseconds)
|
|
{
|
|
_simulateDelayMilliseconds = simulateDelayMilliseconds;
|
|
}
|
|
|
|
public CustomAwaiter GetAwaiter()
|
|
{
|
|
return new CustomAwaiter(_simulateDelayMilliseconds);
|
|
}
|
|
}
|
|
|
|
public class CustomAwaitable<T> : CustomAwaitable
|
|
{
|
|
private readonly T _result;
|
|
|
|
public CustomAwaitable(int simulateDelayMilliseconds, T result)
|
|
: base(simulateDelayMilliseconds)
|
|
{
|
|
_result = result;
|
|
}
|
|
|
|
public new CustomAwaiter<T> GetAwaiter()
|
|
{
|
|
return new CustomAwaiter<T>(_simulateDelayMilliseconds, _result);
|
|
}
|
|
}
|
|
|
|
public class CustomAwaiter : INotifyCompletion
|
|
{
|
|
private IList<Action> _continuations = new List<Action>();
|
|
|
|
public CustomAwaiter(int simulateDelayMilliseconds)
|
|
{
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
Thread.Sleep(simulateDelayMilliseconds);
|
|
lock(_continuations)
|
|
{
|
|
IsCompleted = true;
|
|
|
|
foreach (var continuation in _continuations)
|
|
{
|
|
continuation();
|
|
}
|
|
|
|
_continuations.Clear();
|
|
}
|
|
});
|
|
}
|
|
|
|
public bool IsCompleted { get; private set; }
|
|
|
|
public void OnCompleted(Action continuation)
|
|
{
|
|
lock (_continuations)
|
|
{
|
|
if (IsCompleted)
|
|
{
|
|
continuation();
|
|
}
|
|
else
|
|
{
|
|
_continuations.Add(continuation);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void GetResult()
|
|
{
|
|
}
|
|
}
|
|
|
|
public class CustomAwaiter<T> : CustomAwaiter
|
|
{
|
|
private readonly T _result;
|
|
|
|
public CustomAwaiter(int simulateDelayMilliseconds, T result)
|
|
: base(simulateDelayMilliseconds)
|
|
{
|
|
_result = result;
|
|
}
|
|
|
|
public new T GetResult() => _result;
|
|
}
|
|
|
|
public class CustomException : Exception
|
|
{
|
|
public CustomException() : base("This is a custom exception.")
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|