gpt4 book ai didi

c# - ASP.NET MVC WebAPI 从异步任务创建 ViewModel

转载 作者:行者123 更新时间:2023-11-30 15:25:19 24 4
gpt4 key购买 nike

我使用 ASP.NET MVC WebAPI 编写 Web 应用程序,我想将当前的同步代码转换为异步代码以进行优化。问题是我用从存储库中获取的多个对象填充 ViewModel。来自存储库的这些调用应该是异步的。

假设我有关于这个接口(interface)的存储库调用的签名

public interface ICompanyRepository
{
IEnumerable<Company> GetCompanies();
IEnumerable<Address> GetAddresses();
}

View 模型定义

public class CompaniesFullViewModel
{
public IEnumerable<Company> Companies { get; set; }
public IEnumerable<Address> Addresses { get; set; }
}

和 Controller :

public class CompanyController
{
public readonly ICompanyRepository Repository { get; private set; }

public CompanyController(IRepository repository)
{
Repository = repository;
}

[ResponseType(typeof(CompaniesFullViewModel))]
public HttpResponseMessage Get()
{
var companies = Repository.GetCompanies();
var addresses = Repository.GetAddresses();

HttpStatusCode statusCode = companies.Any()
? HttpStatusCode.OK
: HttpStatusCode.PartialContent;

return
Request.CreateResponse(
statusCode,
new CompaniesFullViewModel
{
Companies = companies,
Addresses = addresses
});
}
}

此外,我还对 Controller 实现了测试:

[TestClass]
public sealed class CompanyTestController : BaseTestController
{
#region Fields

private static Mock<ICompanyRepository> _repositoryMock;
private static CompanyController _controller;

#endregion

[ClassInitialize]
public static void Initialize(TestContext testContext)
{
// Mock repository
_repositoryMock = new Mock<ICompanyRepository>();
DependencyResolver.Default.Container.RegisterInstance(_repositoryMock.Object);

// Create controller
_controller =
DependencyResolver.Default.Container.Resolve<CompanyController>();

// Init request
_controller.Request = new HttpRequestMessage();
_controller.Request.SetConfiguration(new HttpConfiguration());
}

[ClassCleanup]
public static void Cleanup()
{
_controller.Dispose();
}

[TestMethod]
public void Get_ActionExecutes_ReturnsEmptyCompaniesViewModel()
{
var companies = new List<Company>();
var addresses = new List<Address>();

// Setup fake method
_repositoryMock
.Setup(c => c.GetCompanies())
.Returns(companies);
_repositoryMock
.Setup(c => c.GetAddresses())
.Returns(addresses);

// Execute action
var response = _controller.Get();

// Check the response
Assert.AreEqual(HttpStatusCode.PartialContent, response.StatusCode);
}
}

如果存储库是异步的并且签名如下所示,我如何将 Controller 转换为异步:

public interface ICompanyRepository
{
Task<IEnumerable<Company>> GetCompaniesAsync();
Task<IEnumerable<Address>> GetAddressesAsync();
}

最佳答案

您需要做的是将 Controller 操作更改为 async同样,并将返回类型更改为 Task<> .然后您可以等待您的异步存储库调用:

[ResponseType(typeof(CompaniesFullViewModel))]
public async Task<HttpResponseMessage> Get() // async keyword.
{
var companies = await Repository.GetCompaniesAsync(); // await
var addresses = await Repository.GetAddressesAsync(); // await

HttpStatusCode statusCode = companies.Any()
? HttpStatusCode.OK
: HttpStatusCode.PartialContent;

return
Request.CreateResponse(
statusCode,
new CompaniesFullViewModel
{
Companies = companies,
Addresses = addresses
});
}

按照惯例,您还可以将 Controller 操作的名称更改为以 Async 结尾。同样,尽管如果您使用 RESTful 约定和/或路由属性, Controller 操作的实际名称并不重要。

测试

我使用 XUnitNUnit , 但似乎 MSTest 也支持测试 asynchronous methods , 并且 Moq 还提供 Async设置的版本:

[Test]
public async Task Get_ActionExecutes_ReturnsEmptyCompaniesViewModel() // async Task
{
var companies = new List<Company>();
var addresses = new List<Address>();

// Setup fake method
_repositoryMock
.Setup(c => c.GetCompaniesAsync())
.ReturnsAsync(companies); // Async
_repositoryMock
.Setup(c => c.GetAddressesAsync())
.ReturnsAsync(addresses); // Async

// Execute action
var response = await _controller.Get(); // Await

// Check the response
Assert.AreEqual(HttpStatusCode.PartialContent, response.StatusCode);
_repositoryMock.Verify(m => m.GetAddressesAsync(), Times.Once);
_repositoryMock.Verify(m => m.GetCompaniesAsync(), Times.Once);
}

顺便说一句,您似乎正在使用 Setter 依赖注入(inject)。另一种方法是使用构造函数注入(inject),它的好处是确保类始终处于有效状态(即在等待设置依赖项时没有 transient )。这也允许建立依赖项(在这种情况下是您的存储库)readonly .

关于c# - ASP.NET MVC WebAPI 从异步任务创建 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31398545/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com