我在同一个ASP.NET项目中有一个ApiController和一个Controller。我的想法是,我想向第三方公开REST API,并在我公开的REST API之上构建一个网站。
我想从我的MVC控制器(在ProfileController中)中使用REST API(在ProfileApiController中)。两个控制器都需要进行身份验证,ProfileApiController的响应取决于活动的User.Identity。
我怎样才能做到这一点?
以下代码:
namespace Controllers
{
[Authorize]
public class ProfileApiController : ApiController
{
[Route("api/profile/{param}")]
[HttpGet]
public async Task<IHttpActionResult> GetProfile(string param)
{
return this.Ok<IEnumerable<TransferObject>>( /* business logic */ );
}
}
[Authorize]
public class ProfileController : Controller
{
public async Task<ActionResult> GetProfile()
{
//Pseudocode -- this is what I'm looking for
var api = (reference_to_profileapicontroller);
api.Authenticate(User.Identity);
var m = api.GetProfile("myparameter");
//End Pseudocode
return View(m):
}
}
}
我已经尝试了两种方法:
通过HttpClient调用WebApi
HttpClientHandler h = new HttpClientHandler();
var client = new HttpClient(h);
var response = client.GetAsync("http://localhost:4827/api/profile/param/").Result;
var m = await response.Content.ReadAsAsync<List<TransferObject>>();
return View(m);
但是我在这里坚持将身份从Controller传递给ApiController
直接调用Controller
var pc = DependencyResolver.Current.GetService<ProfileController>();
var r = await pc.GetTenseProfile("param");
var rr = await r.ExecuteAsync(System.Threading.CancellationToken.None);
var m = await rr.Content.ReadAsAsync<List<TransferObject>>();
return View(m);
但由于需要配置pc.Configuration和pc.Request,这会变成一团糟。这不应该这么难吗?
答案 0 :(得分:2)
我会按此顺序选择3条路线中的一条。
将Controller
和ApiController
共有的逻辑移到一个类中,然后在控制器中使用该类。
[Authorize]
public class ProfileApiController : ApiController
{
[Route("api/profile/{param}")]
[HttpGet]
public async Task<IHttpActionResult> GetProfile(string param)
{
// have all business logic in this class
ProfileClass = newClass = new ProfileClass();
IList<TransferObject> vm = newClass.GetData(); // from bus rules
return this.Ok<IList<TransferObject>>(vm);
}
}
[Authorize]
public class ProfileController : Controller
{
public async Task<ActionResult> GetProfile()
{
// have all business logic in this class
ProfileClass = newClass = new ProfileClass();
IList<TransferObject> vm = newClass.GetData(); // from bus rules
return View(vm):
}
}
通过AJAX使用您的API。这是更多的服务器往返,但使用您设计的API。使用视图中的参数对API控制器进行AJAX调用。
[Authorize]
public class ProfileController : Controller
{
public async Task<ActionResult> GetProfile()
{
return View("myparameter"):
}
}
使用基于声明的身份验证,其中包含请求中的标头。如果您正在保护您的API,那么您可能已经在这样做了。如上所示使用HttpClient,然后根据MVC中的用户在标头中添加承载令牌。
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
这也可能有所帮助:http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
选项2和3中有很多冗余代码。控制器最好不要理解业务逻辑并让代码消耗掉它。我不认为在每个Action中都要在MVC代码中创建HttpRequests是一个好习惯。当你不得不重构时,这会导致很多令人头痛的问题。