2013-04-23 21 views
5

Posiadamy od dawna działającą aplikację ASP.NET, która urodziła się w .NET 1.1/IIS6 dni. Obecnie korzystamy z platformy .NET4.5/IIS7, ale nic nie zrobiliśmy z MVC.Przepisywanie adresów URL w ASP.NET 4.5 i Web API

Zapewniamy katalog dla klientów i dać im URL mogą używać:

www.ourhost.com/customername 

Korzystanie zwyczaj IHttpModule mamy rozwiniętą ciągniemy „CustomerName” z adresu URL, aby znaleźć klienta w bazie danych. Identyfikator klienta jest następnie przechowywany w kontekście strony * i używany przez praktycznie wszystkie strony w witrynie w celu dostosowania zawartości dla tego klienta. Po tym procesie, powyższy adres URL może być zapisane i przetwarzane jako

www.ourhost.com/index.aspx 

z index.aspx dostępu do ID klienta poprzez jego kontekstu i może to, co robi.

Działa to świetnie i obsługujemy z nim kilka tysięcy klientów. logika przepisywania jest dość złożona, ponieważ sprawdza konta klientów, przekierowuje na stronę "uh oh", jeśli klient jest nieważny i na inną stronę "znajdź dealera", jeśli klient nie zapłacił itp. itp.

Teraz chciałbym zbudować niektóre kontrolery Web API i przerobienie stylu MVC mnie martwi. Widzę wiele przykładów, gdzie zdarza się, aby przepisywanie URL jak tej pracy:

www.ourhost.com/api/{controller} 

ale nadal muszę te API sieci połączeń, aby się zdarzyć w kontekście klienta. Nasze strony stają się coraz bardziej wyrafinowane dzięki asynchronicznym połączeniom JSON/AJAX, ale w odpowiedzi na te połączenia wciąż potrzebuję kontekstu klienta. Chciałbym URL, aby być

www.ourhost.com/customername/api/{controller} 

Ale jestem zakłopotany, jak skonfigurować routing, aby to zrobić i to grać ładnie z naszej IHttpModule.

Czy to możliwe?

* AKTUALIZACJA: Kiedy mówię "zapisany w kontekście strony" mam na myśli HttpContext powiązany z każdym żądaniem internetowym, który zawiera słownik, w którym mogę przechowywać pewne dane dotyczące strony/żądania.

+0

Kiedy mówisz "zapisany w kontekście strony" - czy odnosisz się do obiektu 'Sesja', czy też piszesz bezpośrednio do' Cookie' jakiegoś rodzaju? Ponieważ oznaczono to jako 'web-api', robi to niewielką różnicę. –

+0

@ Troy: Dziękuję za komentarz - zaktualizowałem moje pytanie z wyjaśnieniem. – n8wrl

+0

Rozumiem - używasz 'HttpContext.Current.User' do śledzenia kto jest zalogowanym użytkownikiem? Jak utrzymujesz go w kolejnych rozmowach, które nie zawierają nazwy użytkownika użytkownika w adresie URL? –

Odpowiedz

2

Są dwie części odpowiedzi na twój problem, które mogę zobaczyć.

Utrzymanie Info o użytkownikach w wielu wniosków Ogólnie aplikacja MVC API będzie bezpaństwowcem, czyli nie zachowuje aktualny stan sesji użytkowników pomiędzy żądaniami. Cóż, to jest to, czego nauczyłem się lub byłem głoszony wiele razy podczas pisania API RESTFul.

To zostało powiedziane, można włączyć stanu sesji w MVC Web API poprzez dodanie następujących do Global.asax.cs

protected void Application_PostAuthorizeRequest() 
    { 
     // To enable session state in the WebAPI. 
     System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); 
    } 

zatwierdzających Klient we Wniosku Jak wykazano w Zażądaj adresu URL, aby dodać nazwę klienta, a następnie przechwyć go i przekaż do tej samej procedury, którą dzwoni Twój obecny moduł http, aby autoryzować na żądanie. Możesz to zrobić za pomocą filtra MVC.

Najpierw wykonaj podobny wzorzec adresu URL, aby zarejestrować nazwę klienta w WebApiConfig.cs, coś takiego;

 config.Routes.MapHttpRoute(
      name: "WithCustomerApi", 
      routeTemplate: "api/{customername}/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

Następnie dodać ActionFilter do API kontrolera, który przetwarza każdy wniosek, sprawdza bieżące informacje o sesji, aw razie potrzeby wzywa swój kod odnośnika Autoryzacja/klienta, a następnie zapisuje do stanu sesji do późniejszego wykorzystania. Lub jeśli żadna dobra informacja od klienta nie może wysłać na nową trasę MVC

Dodamy więc atrybut podobny do tego;

[WebApiAuthentication] 
public class BaseApiController : ApiController 
{ 
} 

Następnie należy utworzyć filtr działania, który może wyglądać tak (uwaga nie testowałem tego, po prostu zrobić na wzór jak).

public class WebApiAuthenticationAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     var routeData = actionContext.ControllerContext.Request.GetRouteData(); 
     var currentContext = HttpContext.Current; 

     if (routeData.Route.RouteTemplate.Contains("customername")) 
     { 
      try 
      { 
       var authenticated = currentContext.Request.IsAuthenticated; 
       if (!authenticated) 
       { 
        var customer = routeData.Values["customername"]; 
        // do something with customer here and then put into session or cache 
        currentContext.Session.Add("CustomerName", customer); 
       } 
      } 
      catch (Exception exception) 
      { 
       var error = exception.Message; 
       // We dont like the request 
       actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest); 
      } 
     } 
     else 
     { 
      // No customer name specified, send bad request, not found, what have you ... you *could* potentially redirect but we are in API so it probably a service request rather than a user 
      actionContext.Response = new HttpResponseMessage(HttpStatusCode.NotFound); 
     } 

    } 
} 

Jeśli utworzyć nowy MVC 5 Web API aplikację i dodać w tych dodatków i umieścić filtr na regulatorze wartości domyślne jak więc powinieneś być w stanie zobaczyć ten pracuje jako demo możliwego rozwiązania.

Powoduje wyświetlenie nazwy klienta, jeśli wszystko działa poprawnie.

[WebApiAuthentication] 
public class ValuesController : ApiController 
{ 
    // GET api/values 
    public IEnumerable<string> Get() 
    { 
     var session = HttpContext.Current.Session; 

     if (session != null) 
     { 
      return new string[] {"session is present", "customer is", session["CustomerName"].ToString()}; 
     } 

     return new string[] { "value1", "value2" }; 
    } 

} 

ofiaruję to jako możliwego rozwiązania, jak mówię, nie religijne argumenty dotyczące przechowywania sesji i autoryzacji w API, ale nie są to pytanie. Nadzieja, która pomaga, Steve

Powiązane problemy