我有MVC5项目,从控制器需要调用webapi方法。 Webapi由基于令牌的身份验证实现。因此我必须为每个调用传递令牌。我使用下面的代码在httpheader中传递令牌。
HttpClient httpClient = new HttpClient();
string baseUrl = "http://localhost:60477/";
dynamic token = Session["token"];
if (token.AccessToken != null)
{
httpClient.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", token.AccessToken));
}
我在我的控制器中有多个动作方法,比如,我想使用单个httpclient,并且需要在一个地方添加标题,而是在每个动作方法中添加标题。我可以将httpclient标题注册码放在mvc应用程序中,以便所有控制器都可以使用。这意味着我不想重复代码,比如在每个动作方法中添加令牌。我怎么能这样做
Public ActionResult Postuser(UserModel user)
{
//post code
}
Public ActionResult getuser(UserModel user)
{
HttpResponseMessage response = httpClient.GetAsync(baseUrl + "api/Admin/GetStates").Result;
if (response.IsSuccessStatusCode)
{
string stateInfo = response.Content.ReadAsStringAsync().Result;
}
}
Public ActionResult PostRoles(RoleModel role)
{
//post roles code
}
答案 0 :(得分:2)
最好遵守单一责任原则,并在其自己的班级中提取与其他服务的互动,例如
public class ServiceClient : IServiceClient
{
private HttpClient m_Client;
public ServiceClient
{
m_Client = new HttpClient();
// Initialize the client as you need here
}
public void CallSomeMethod()
{
// Call method on the client
}
}
然后在控制器中注入IServiceClient并调用它的方法。如果你不使用注入(我建议你这样做),你可以在控制器的构造函数中创建一个新实例。
答案 1 :(得分:1)
您可以尝试在控制器中使用动作过滤器。尝试添加看起来像这样的覆盖 -
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// some condition code to target a specific method in the controller
// Example
if (filterContext.ActionDescriptor.ActionName == "getuser") // <-- your method
{
// put your token based authentication code here
}
base.OnActionExecuting(filterContext);
}
OnActionExecuting方法位于控制器范围内,因此您可以为不同的控制器使用不同的逻辑。
如果要在操作方法之后运行代码,还有一个OnActionExecuted方法覆盖。
------编辑--------------
至于放置HttpClient代码段的位置,您可以试试这个 -
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpClient httpClient = new HttpClient();
string baseUrl = "http://localhost:60477/";
dynamic token = Session["token"];
if (token.AccessToken != null)
{
httpClient.DefaultRequestHeaders.Add(
"Authorization",
string.Format("Bearer {0}", token.AccessToken)
);
httpClient.BaseAddress = new Uri(baseUrl);
}
if(filterContext.ActionParameters.ContainsKey("httpClient"))
{
filterContext.ActionParameters["httpClient"] = httpClient;
}
else
{
// error
}
base.OnActionExecuting(filterContext);
}
因此,在OnActionExecuting中建立了HttpClient对象以及baseUrl的赋值。此代码将在您重构的控制器中返回ActionResult的任何方法之前运行。如果您想要定位一些而不是所有方法,请参阅上面的OnActionExecuting的第一个示例。
public ActionResult getuser(UserModel user, HttpClient httpClient)
{
HttpResponseMessage response = httpClient.GetAsync("api/Admin/GetStates").Result;
if(response.IsSuccessStatusCode)
{
string stateInfo = response.Content.ReadAsStringAsync().Result;
}
// the rest of your code for getuser..
return View();
}
现在你的getuser方法有一个额外的参数(HttpClient httpClient)。
答案 2 :(得分:0)
为什么不在Global asax中移动代码或创建自定义属性?
这是一个很好的链接: http://www.diaryofaninja.com/blog/2011/07/24/writing-your-own-custom-aspnet-mvc-authorize-attributes