如何从控制器中提取方法?
How to extract methods from controller?
我想将“我能做的”提取到服务中。我在控制器中有这个方法:
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
LoginViewModel loginViewModel = new LoginViewModel
{
ReturnUrl = returnUrl,
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList()
};
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
return View("Login", loginViewModel);
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
ModelState.AddModelError(string.Empty, "Error loading external login information.");
return View("Login", loginViewModel);
}
var signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (signInResult.Succeeded)
{
return LocalRedirect(returnUrl);
}
else
{
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
if (email != null)
{
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
user = new ApplicationUser
{
UserName = info.Principal.FindFirstValue(ClaimTypes.Email),
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
await _userManager.CreateAsync(user);
}
await _userManager.AddLoginAsync(user, info);
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
ViewBag.ErrorTitle = $"Nie otrzymano informacji o adresie e-mail od dostawcy: {info.LoginProvider}";
ViewBag.ErrorMessage = "Proszę skontaktować się z supportem fryzjer@aplikacjafryzjer.com";
return View("Error");
}
}
某些属性仅适用于从 Controller 继承的 类,例如。模型状态或 Url。
我也可以提取代码的这些部分吗? service可以继承controller,那不就变成controller了吗?
-------------------------------------------- - - - - - - - - 编辑 - - - - - - - - - - - - - - - - - ----------------------------
好的,我尝试将我的方法与控制器分开。在我之前的代码控制器下面:
public class AccountController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailService _emailService;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailService emailService)
{
_userManager = userManager;
_signInManager = signInManager;
_emailService = emailService;
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
//register functionality
var user = new ApplicationUser
{
FirstName = model.FirstName,
LastName = model.LastName,
UserName = model.Email,
Email = model.Email,
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
if (_signInManager.IsSignedIn(User) && User.IsInRole("Admin"))
{
return RedirectToAction("ListUsers", "Administrator");
}
//login user
await _signInManager.SignInAsync(user, isPersistent: false);
//generation of the email token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var link = Url.Action(nameof(VerifyEmail), "Home", new { userId = user.Id, code }, Request.Scheme, Request.Host.ToString());
await _emailService.SendAsync(user.Email, "Weryfikacja adresu e-mail", $"<a href=\"{link}\">Potwierdź e-mail</a>", true);
return RedirectToAction("EmailVerification");
}
}
return View(model);
}
}
现在我的控制器:
public class AccountController : Controller
{
private readonly IUserManager _userManager;
public AccountController(
IUserManager userManager)
{
_userManager = userManager;
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
(string action, string controller) = await _userManager.Register(model);
return RedirectToAction(action, controller);
}
return View(model);
}
}
我敢肯定,出了点问题。我不知道如何将此逻辑与控制器分开,但在其他论坛上我听说“你必须将你的逻辑与控制器分开!你的控制器必须简单 - 仅获取请求并发送响应,仅此而已!”。但是现在,当我开始重建我的项目时,我不确定这是否更复杂...
在我的服务中我return一个元组(???),因为我没有更好的主意...
public async Task<(string, string)> Register(RegisterViewModel model)
{
//register functionality
var user = new ApplicationUser
{
FirstName = model.FirstName,
LastName = model.LastName,
UserName = model.Email,
Email = model.Email,
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
if (_signInManager.IsSignedIn(User) && User.IsInRole("Admin"))
{
return ("ListUsers", "Administrator");
}
//login user
await _signInManager.SignInAsync(user, isPersistent: false);
//generation of the email token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var link = _urlHelper.Action(nameof(VerifyEmail), "Home", new { userId = user.Id, code });
await _emailService.SendAsync(user.Email, "Weryfikacja adresu e-mail", $"<a href=\"{link}\">Potwierdź e-mail</a>", true);
return ("EmailVerification", "Administrator");
}
return ("Register", "Administrator");
}
据我所知,如果你想在其他不是从控制器继承的自定义服务中使用 Url
。您可以注入 IActionContextAccessor
并使用 IUrlHelperFactory
来创建它。此外,如果您想使用其他基于 属性 或方法的控制器,您可以参考 asp.net core source codes 并找到它,然后您可以自己编写代码。
更多详情,您可以参考以下代码:
首先,您可以在 startup.cs ConfigureServices 方法中注入 IActionContextAccessor:
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
然后您可以使用 DI 和工厂来创建 URLhelper,如下所示:
public class GetRoute : IGetRoute
{
private IUrlHelper _urlHelper;
private IActionContextAccessor _IActionContextAccessor;
public IUrlHelper Url
{
get
{
if (_urlHelper == null)
{
_urlHelper = _urlHelperFactory.GetUrlHelper(_IActionContextAccessor.ActionContext);
}
return _urlHelper;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_urlHelper = value;
}
}
private readonly IUrlHelperFactory _urlHelperFactory ;
public GetRoute(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider, IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
{
_IActionContextAccessor = actionContextAccessor;
_urlHelperFactory = urlHelperFactory;
}
public string Getlink() {
return Url.Link("default", "aaaa");
}
}
我想将“我能做的”提取到服务中。我在控制器中有这个方法:
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
LoginViewModel loginViewModel = new LoginViewModel
{
ReturnUrl = returnUrl,
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList()
};
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
return View("Login", loginViewModel);
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
ModelState.AddModelError(string.Empty, "Error loading external login information.");
return View("Login", loginViewModel);
}
var signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (signInResult.Succeeded)
{
return LocalRedirect(returnUrl);
}
else
{
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
if (email != null)
{
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
user = new ApplicationUser
{
UserName = info.Principal.FindFirstValue(ClaimTypes.Email),
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
await _userManager.CreateAsync(user);
}
await _userManager.AddLoginAsync(user, info);
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
ViewBag.ErrorTitle = $"Nie otrzymano informacji o adresie e-mail od dostawcy: {info.LoginProvider}";
ViewBag.ErrorMessage = "Proszę skontaktować się z supportem fryzjer@aplikacjafryzjer.com";
return View("Error");
}
}
某些属性仅适用于从 Controller 继承的 类,例如。模型状态或 Url。 我也可以提取代码的这些部分吗? service可以继承controller,那不就变成controller了吗?
-------------------------------------------- - - - - - - - - 编辑 - - - - - - - - - - - - - - - - - ----------------------------
好的,我尝试将我的方法与控制器分开。在我之前的代码控制器下面:
public class AccountController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailService _emailService;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailService emailService)
{
_userManager = userManager;
_signInManager = signInManager;
_emailService = emailService;
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
//register functionality
var user = new ApplicationUser
{
FirstName = model.FirstName,
LastName = model.LastName,
UserName = model.Email,
Email = model.Email,
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
if (_signInManager.IsSignedIn(User) && User.IsInRole("Admin"))
{
return RedirectToAction("ListUsers", "Administrator");
}
//login user
await _signInManager.SignInAsync(user, isPersistent: false);
//generation of the email token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var link = Url.Action(nameof(VerifyEmail), "Home", new { userId = user.Id, code }, Request.Scheme, Request.Host.ToString());
await _emailService.SendAsync(user.Email, "Weryfikacja adresu e-mail", $"<a href=\"{link}\">Potwierdź e-mail</a>", true);
return RedirectToAction("EmailVerification");
}
}
return View(model);
}
}
现在我的控制器:
public class AccountController : Controller
{
private readonly IUserManager _userManager;
public AccountController(
IUserManager userManager)
{
_userManager = userManager;
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
(string action, string controller) = await _userManager.Register(model);
return RedirectToAction(action, controller);
}
return View(model);
}
}
我敢肯定,出了点问题。我不知道如何将此逻辑与控制器分开,但在其他论坛上我听说“你必须将你的逻辑与控制器分开!你的控制器必须简单 - 仅获取请求并发送响应,仅此而已!”。但是现在,当我开始重建我的项目时,我不确定这是否更复杂...
在我的服务中我return一个元组(???),因为我没有更好的主意...
public async Task<(string, string)> Register(RegisterViewModel model)
{
//register functionality
var user = new ApplicationUser
{
FirstName = model.FirstName,
LastName = model.LastName,
UserName = model.Email,
Email = model.Email,
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
if (_signInManager.IsSignedIn(User) && User.IsInRole("Admin"))
{
return ("ListUsers", "Administrator");
}
//login user
await _signInManager.SignInAsync(user, isPersistent: false);
//generation of the email token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var link = _urlHelper.Action(nameof(VerifyEmail), "Home", new { userId = user.Id, code });
await _emailService.SendAsync(user.Email, "Weryfikacja adresu e-mail", $"<a href=\"{link}\">Potwierdź e-mail</a>", true);
return ("EmailVerification", "Administrator");
}
return ("Register", "Administrator");
}
据我所知,如果你想在其他不是从控制器继承的自定义服务中使用 Url
。您可以注入 IActionContextAccessor
并使用 IUrlHelperFactory
来创建它。此外,如果您想使用其他基于 属性 或方法的控制器,您可以参考 asp.net core source codes 并找到它,然后您可以自己编写代码。
更多详情,您可以参考以下代码:
首先,您可以在 startup.cs ConfigureServices 方法中注入 IActionContextAccessor:
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
然后您可以使用 DI 和工厂来创建 URLhelper,如下所示:
public class GetRoute : IGetRoute
{
private IUrlHelper _urlHelper;
private IActionContextAccessor _IActionContextAccessor;
public IUrlHelper Url
{
get
{
if (_urlHelper == null)
{
_urlHelper = _urlHelperFactory.GetUrlHelper(_IActionContextAccessor.ActionContext);
}
return _urlHelper;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_urlHelper = value;
}
}
private readonly IUrlHelperFactory _urlHelperFactory ;
public GetRoute(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider, IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
{
_IActionContextAccessor = actionContextAccessor;
_urlHelperFactory = urlHelperFactory;
}
public string Getlink() {
return Url.Link("default", "aaaa");
}
}