web-dev-qa-db-de.com

rufen Sie die Web-API vom MVC-Controller aus auf und verwenden Sie denselben httpclient

Ich habe MVC5-Projekt, vom Controller muss die Webapi-Methode aufgerufen werden. Webapi durch tokenbasierte Authentifizierung implementiert. Daher muss ich das Token für jeden Aufruf übergeben. Ich benutze den folgenden Code, um das Token in httpheader zu übergeben.

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));
            }

Ich habe mehrere Aktionsmethoden in meinem Controller, ich möchte einen einzelnen httpclient verwenden und Header müssen an einer Stelle hinzugefügt werden, anstatt Header in jeder einzelnen Aktionsmethode hinzuzufügen. Wo kann ich httpclient Header Registrierungscode in MVC Application für alle Controller gemeinsam platzieren. Das bedeutet, dass ich den Code nicht wie das Hinzufügen eines Tokens in jeder einzelnen Aktionsmethode wiederholen möchte. wie kann ich das machen

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
}
4
SivaRajini

Sie können versuchen, eine kleine Hilfsklasse zum Erstellen Ihres httpclient-Objekts zu erstellen. So etwas wie

public class HttpClientHelper
{
    public static HttpClient GetHttpClient()
    {
        var MyHttpClient = new HttpClient();
        dynamic _token = HttpContext.Current.Session["token"];
        if (_token == null) throw new ArgumentNullException(nameof(_token));
        MyHttpClient.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", _token.AccessToken));
        return MyHttpClient;
    }
}

und nenne es dann in deinen Controllern als

public ActionResult getuser(UserModel user)
{
    var httpClient = HttpClientHelper.GetHttpClient();
    HttpResponseMessage response = httpClient.GetAsync(baseUrl + "api/Admin/GetStates").Result;
    if (response.IsSuccessStatusCode)
    {
        string stateInfo = response.Content.ReadAsStringAsync().Result;
    }
}
6
Dandy

Es ist besser, das Prinzip der Einzelverantwortung einzuhalten und die Interaktion mit einem anderen Dienst in einer eigenen Klasse zu extrahieren, z.

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
    }
}

Dann injizieren Sie den IServiceClient in Ihren Controller und rufen dessen Methoden auf. Wenn Sie keine Injection verwenden (was ich Ihnen rate), können Sie einfach eine neue Instanz im Konstruktor des Controllers erstellen.

2

Sie können versuchen, einen Aktionsfilter in Ihrem Controller zu verwenden. Versuchen Sie, eine Außerkraftsetzung hinzuzufügen, die ungefähr so ​​aussieht:

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);
}

Die OnActionExecuting-Methode befindet sich im Bereich des Controllers, sodass Sie für verschiedene Controller unterschiedliche Logik haben können.

Es gibt auch eine OnActionExecuted-Methodenüberschreibung, wenn Sie Code nach Ihrer Aktionsmethode ausführen möchten.

------bearbeiten--------------

Was den Speicherort Ihres HttpClient-Code-Snippets betrifft, können Sie Folgendes versuchen:

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);
}

Daher wird das HttpClient-Objekt zusammen mit der Zuweisung Ihrer baseUrl in OnActionExecuting eingerichtet. Dieser Code wird ausgeführt, bevor eine Methode in dem Controller, den Sie überarbeiten, ein ActionResult zurückgibt. Wenn Sie auf einige und nicht alle Methoden abzielen möchten, lesen Sie das obige erste Beispiel für 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();
}

Jetzt hat Ihre getuser-Methode einen zusätzlichen Parameter (HttpClient httpClient).

1
alphaneer

warum verschiebst du den Code nicht in Global asax oder erstellst ein benutzerdefiniertes Attribut?

hier ist ein guter Link: http://www.diaryofaninja.com/blog/2011/07/24/writing-your-own-custom-aspnet-mvc-authorize-attributes

0
Petar Minev