Teil 1: Grundlagen

Web-APIs mit ASP.NET MVC 6
Kommentare

Mit ASP.NET MVC und ASP.NET Web API existierten jahrelang zwei sehr ähnliche Frameworks nebeneinander. Um Mehrgleisigkeiten zu vermeiden, integriert das Produktteam die Möglichkeiten von Web-API künftig in MVC 6. 

Mit ASP.NET 5 und .NET Core will Microsoft eine neue Ära von .NET einläuten. Das Framework soll modularer sowie plattformunabhängig werden. Außerdem sollen verschiedene Versionen künftig einfacher nebeneinander auf einem Server betrieben werden können. Da dieser nach über zwölf Jahren durchgeführte Frühjahrsputz ohnehin Breaking Changes notwendig macht, nutzt Microsoft die Gelegenheit, Mehrgleisigkeiten zu entfernen. Dazu gehört die Tatsache, dass in den letzten Jahren mit ASP.NET MVC und ASP.NET Web API zwei sehr ähnliche Frameworks nebeneinander existierten. Während der Fokus bei MVC auf Webanwendungen und bei Web-API auf HTTP-basierten Services – so genannten Web-APIs – lag, teilten sie viele zum Teil nur geringfügig anders implementierte Konzepte, wie Controller, Model, Model Binding oder Routing.

Überblick Artikelserie

  • Teil 1: Grundlagen
  • Teil 2: Weiterführende Themen wie Formatter u. a.

Um diesen Umstand aus der Welt zu schaffen, wird ASP.NET Web API in ASP.NET MVC 6 aufgehen. Dieser Artikel zeigt, wie MVC 6 künftig für die Entwicklung von Web-APIs genutzt werden kann. Am einfachsten lassen sich die hier gezeigten Beispiele mit der aktuellen CTP von Visual Studio 2015 nachstellen.

Ein erstes Web-API mit MVC 6

Wie beim Vorgänger MVC 5 und seiner Schwestertechnologie ASP.NET Web API üblich, stellen Controller serverseitige Routinen zur Verfügung. Die einfachste und häufigste Möglichkeit, Controller bereitzustellen, besteht darin, Controller von der Basisklasse zu erben. Standardmäßig stellt MVC sämtliche Methoden der Controller-Klassen, die sich in diesem Kontext auch Action-Methoden nennen, über HTTP zur Verfügung. Dazu kommt ein als Routing bezeichneter Mechanismus zum Einsatz, der URLs auf Action-Methoden abbildet. Wird die Projektvorlage von Visual Studio genutzt, herrscht standardmäßig eine Route vor, die sich wie folgt gestaltet:

 {controller}/{action}/{id?}

Der Platzhalter {controller} steht dabei für den Namen des Controllers. In der Regel ist dies der Name der Controller-Klasse ohne Endung Controller. Der Name des durch die Klasse FlugController beschriebenen Controllers ist somit Flug. Den Namen der aufzurufenden Action-Methode spiegelt der Platzhalter {action} wieder. Auf Groß-/und Kleinschreibung legt MVC an dieser Stelle keinen Wert. Der optionale Platzhalter {id?} steht für einen Wert, der an einen Parameter mit dem Namen id zu übergeben ist. Das Fragezeichen am Ende des Parameternamens drückt aus, dass die Angabe dieses Werts bzw. das Vorhandensein eines Parameters id optional ist.

Ein Aufruf des URLs Flug/GetById/17 führt somit dazu, dass MVC die Methode GetById des Controllers FlugController aufruft und den Wert 17 an dessen Parameter id übergibt. Da es sich bei {id} um einen optionalen Platzhalter handelt und MVC sämtliche URL-Parameter standardmäßig auf gleichnamige Parameter der adressierten Action-Methode abbildet, könnte sich dieser Aufruf auch wie folgt gestalten: Flug/GetById?id=17.

Ein Beispiel für solch einen Controller findet sich in Listing 1. Zur Vereinfachung verwaltet er Flüge in einer statischen Liste, die sein Konstruktor initialisiert, sofern sie noch nicht vorhanden ist. Darüber hinaus weist er einige Action-Methoden auf, die MVC 6 anhand der besprochenen Route auf URLs abbildet. Diese Methoden rufen Flüge nach bestimmten Kriterien ab oder geben die Möglichkeit, sie zu bearbeiten. Liefern Sie ein Objekt retour, wird dieses von einem Mechanismus, der sich Output Formatter nennt, in ein Übertragungsformat serialisiert. Das Ergebnis der Serialisierung wird von MVC 6 zum Aufrufer übertragen. Im Lieferumfang befinden sich Output Formatter für die Datenformate JSON und XML. Weitere Output Formatter kann der Entwickler bereitstellen. Standardmäßig kommt JSON zum Einsatz. Der Aufrufer kann jedoch unter Verwendung der HTTP-Kopfzeile Accept andere Formate anfordern.

Wie bereits angemerkt, bildet MVC standardmäßig sämtliche URL-Parameter auf gleichnamige Parameter der Action-Methoden ab. Möchte der Entwickler jedoch angeben, dass sich ein Parameter aus den übersendeten Nutzdaten ergibt, annotiert er diesen mit dem Attribut FromBody. Ein Beispiel dafür ist der Parameter flug der Action-Methode PostFlug in Listing 1. Das Parsen der Nutzdaten übernimmt ein so genannter Input Formatter. Anhand des Datenformats, das der Aufrufer über die Kopfzeile Content-Type angibt, wählt MVC einen passenden Input Formatter, der sich um das Deserialisieren der Nutzdaten in einen Typ des Parameters kümmert. Analog zu den Output Formattern befinden sich auch Input Formatter für JSON und XML im Lieferumfang.

 public class FlugController : Controller
{
  private static List fluege;

  public FlugController()
  {
    if (fluege == null)
    {
      fluege = new List();
      fluege.Add(new Flug { [...] });
      [...]
    }
  }

  public Flug GetById(int id)
  {
    return fluege.FirstOrDefault(f => f.FlugId == id);
  }

  public Flug GetByFlugNumberAndDate(string flugNummer, DateTime datum)
  {
    return fluege.FirstOrDefault(
      f => f.FlugNr == flugNummer && f.Datum.Date == datum.Date);
  }

  public List GetAll()
  {
    return fluege;
  }

  public List GetByRoute(string abflugOrt, string zielOrt)
  {
    return fluege.Where(f => f.AbflugOrt == abflugOrt 
      && f.ZielOrt == zielOrt).ToList();
  }

  public void PostFlug([FromBody]Flug flug)
  {
    flug.FlugId = fluege.Max(f => f.FlugId) + 1;
    fluege.Add(flug);
  }

}

Auf HTTP-Methoden einschränken

Im Gegensatz zu ASP.NET Web API geben die Namen der Action-Methode keine Auskunft über die HTTP-Methoden (Verben), für die sie gedacht sind. Vielmehr kann der Aufrufer standardmäßig alle Action-Methoden unter Verwendung jeder HTTP-Methode anstoßen. Attribute wie HttpGet, HttpPost, HttpPatch, HttpPut oder HttpDelete bieten jedoch die Möglichkeit, Action-Methoden auf bestimmte HTTP-Methoden zu beschränken. Um anzugeben, dass eine Action-Methode nur bei POST-Aufrufen in Erwägung zu ziehen ist, annotiert der Entwickler diese beispielsweise mit HttpPost:

[HttpPost]
public void PostFlug([FromBody]Flug flug) { ... }

Alternativ besteht die Möglichkeit, die zu akzeptierenden HTTP-Methoden als Parameter an das Attribut AcceptVerbs zu übergeben. Dies ist nützlich, um HTTP-Methoden, für die keine eigenen Attribute zur Verfügung stehen, zu konfigurieren:

[AcceptVerbs("POST")]
public void PostFlug([FromBody]Flug flug)

Web-API testen

Zum Testen von Web-API bieten sich Werkzeuge zum manuellen Erzeugen von HTTP-Anfragen an. Ein Beispiel dafür ist Fiddler. Eine damit versendete GET-Anfrage, die sich an die in Listing 1 gezeigte Action-Methode GetById richtet, gestaltet sich wie folgt:

GET http://localhost:1196/flug/GetById/1 HTTP/1.1
User-Agent: Fiddler
Host: localhost:1196

In den Nutzdaten der darauffolgenden Antwort findet sich eine Repräsentation des retournierten Flug-Objektes wieder. Standardmäßig kommt hierfür JSON zum Einsatz. Über das tatsächliche Datenformat gibt die Kopfzeile Content-Type Auskunft:

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Server: Microsoft-IIS/8.0
Date: Mon, 02 Feb 2015 11:22:53 GMT
Content-Length: 131

{"FlugId":1,"FlugNr":"LH4711", [...]}

Um für die Antwort ein anderes Datenformat anzufordern, nutzt der Aufrufer die Kopfzeile Accept. Mit Accept: text/xml fordert er beispielsweise eine XML-Repräsentation der abgerufenen Ressourcen an:

 GET http://localhost:1196/flug/GetById/1 HTTP/1.1
User-Agent: Fiddler
Host: localhost:1196
Accept: text/xml

URLs mit Routing beeinflussen

Wie das vorangegangene Beispiel gezeigt hat, kommt der Name der adressierten Action-Methode beim Einsatz der Standardroute in dem URL vor. Das ist zwar legitim, entspricht jedoch nicht den Ideen hinter HTTP und REST, wonach ein URL eine konkrete Ressource und nicht Operationen referenziert. Will der Entwickler diesen Ideen folgen, ist es notwendig, eigene Routen einzurichten. Dies kann an globaler Stelle oder mit Attributen bei den einzelnen Controllern bzw. Action-Methoden erfolgen.

Die globale Routing-Konfiguration findet sich in der Datei Startup.cs, die unter anderem MVC mit UseMvc einrichtet und an diese Methode über einen Lambda-Ausdruck eine Routenkonfiguration übergibt:

app.UseMvc(routes => {
  routes.MapRoute(
    name: "default",
    template: "{controller}/{action}/{id?}",
    defaults: new { controller = "Home", action = "Index" });
});

Diese richtet die diskutierte Standardroute mit MapRoute ein. Der Parameter name legt einen eindeutigen Namen für die Route fest und der Parameter template beschreibt den mit der Route assoziierten URL. Das auf den Platzhalter id folgende Fragezeichen gibt an, dass der damit ausgedrückte Routing-Parameter optional ist. Mit dem Parameter defaults legt die Routenkonfiguration fest, welche Werte für die Platzhalter controller und action zu nutzen sind, wenn der Aufrufer diese nicht explizit in dem URL anführt. Die hierfür von der Projektvorlage vorgesehenen Werte Home und Index führen zur Startseite der Webanwendung.

Durch weitere Aufrufe von MapRoute im Rahmen des betrachteten Lambda-Ausdrucks kann der Entwickler weitere Routen angeben, die zu bestimmten Action-Methode führen. Handelt es sich dabei um Routen, die nur für eine oder wenige Action-Methoden gelten, ist es einfacher, sie direkt im betroffenen Controller mit Attributen einzurichten. Ein Beispiel dafür findet sich in Listing 2. Es definiert mit dem Attribut Route eine Route, die zum Controller führt. Als URL-Vorlage definiert es api/[controller], wobei [controller] ein Platzhalter für den Namen des aktuellen Controllers ist. Wie üblich setzt MVC in diesen Platzhalter standardmäßig den Namen der Controller-Klasse ohne Endung Controller ein. Im betrachteten Fall ist dies der Wert Flug, zumal sich die Klasse FlugController nennt.

•	GET api/[controller]/{id: int} für GetById
•	GET api/[controller]/{datum}/{flugNummer} für GetByFlugNumberAndDate
•	GET api/[controller] für GetAll
•	GET api/[controller]/{abflugOrt}-{zielOrt} für GetByRoute
•	POST api/[controller] für PostFlug

Demzufolge bewirkt ein Aufruf des URLs api/flug/17 mittels GET beispielsweise, dass MVC die Action-Methode GetById anstößt und an deren Parameter id den Wert 17 übergibt.

Bei genauerer Betrachtung dieser Route fällt auf, dass das dahinterstehende URL-Template definiert, dass es sich beim Wert für den Routing-Parameter id um einen Integer handeln muss. Dies drückt sich durch den Zusatz int aus, der dem Routing-Parameter gefolgt von einem Doppelpunkt nachgestellt wird. Solche Zusätze nennen sich Routing-Constraints (Routing-Einschränkungen). Informationen über die mit MVC 6 ausgelieferten Routing-Constraints finden sich im .NET Web Development and Tools Blog.

[Route("api/[controller]")]
public class FlugController : Controller
{
  [...]

  [HttpGet("{id:int}")]
  public Flug GetById(int id) { [...] }

  [HttpGet("{datum}/{flugNummer}")]
  public Flug GetByFlugNumberAndDate(string flugNummer, DateTime datum) {
    [...] 
  }

  [HttpGet]
  public List GetAll() { [...] }

  [HttpGet("{abflugOrt}-{zielOrt}")]
  public List GetByRoute(string abflugOrt, string zielOrt) { [...] }

  [HttpPost]
  public void PostFlug([FromBody]Flug flug) { [...] }

Neben den hier betrachteten Möglichkeiten kann der Entwickler den Routing-Parameter durch Anhängen eines Fragezeichens als optional kennzeichnen: {abflugOrt}-{zielOrt?}.

Alternativ dazu kann ein Routing-Parameter auch einen Standardwert erhalten. Diesen zieht der Routing-Mechanismus heran, wenn beim Aufruf eines URLs kein Wert für den Routing-Parameter angeführt wurde: {abflugOrt}-{zielOrt=Rom}.

WebApiCompatShim

Wenngleich ASP.NET-Web-API dem Framework ASP.NET MVC sehr ähnlich ist, unterscheidet es sich merklich bei der Auswahl der für einen Aufruf auszuführenden Action-Methode. Beispielsweise ist es beim Einsatz von Web-API üblich, dass sich mehrere Action-Methoden denselben URL teilen. Das ist möglich, zumal Web-API die Action-Methode nicht nur in Abhängigkeit des URLs sondern auch unter Berücksichtigung der genutzten HTTP-Methode sowie der übersendeten URL-Parameter auswählt. Aber auch an anderen Stellen ist man mit Implementierungsunterschieden konfrontiert.Diese Unterschiede erschweren die Portierung bestehender Codes erheblich. Um diese Aufgabe zu vereinfachen, unterstützt Microsoft mit einer Komponente namens WebApiCompatShim (Microsoft.AspNet.Mvc.WebApiCompatShim), die via NuGet zu laden ist. Diese Komponente tauscht einige MVC-interne Komponenten durch eigene aus, die das Verhalten von Web-API nachahmen.Um in den Genuss von WebApiCompatShim zu kommen, referenziert man diese über die Datei project.json, was zur Folge hat, dass Visual Studio sie via NuGet bezieht. Damit MVC 6 diese Komponente auch nutzt, muss sie innerhalb der Klasse Startup referenziert werden. Darüber hinaus ist der Entwickler angehalten, eine Route hierfür anzulegen. Beim Einsatz der von Visual Studio gebotenen Projektvorlage sind diese drei Schritte in den beiden genannten Dateien bereits durch entsprechende Kommentare angedeutet.

Mit HTTP arbeiten

Über ihre Parameter erhalten Action-Methoden Zugriff auf die URL-Parameter einer HTTP-Anfrage sowie auf die übersendeten Nutzdaten. Über den jeweiligen Rückgabewert können sie hingegen die Nutzdaten der HTTP-basierten Antwort beeinflussen.

Um an weitere Informationen zu kommen, die sich in der Anfrage verbergen, können Action-Methoden auf die von der Basisklasse Controller geerbte Eigenschaft Request zurückgreifen. Auf diese Weise lassen sich beispielsweise übersendete Kopfzeilen auslesen. Analog dazu können Action-Methoden über die von Controller geerbte Eigenschaft Response die Antwort beeinflussen und so Kopfzeilen oder auch den Statuscode der Antwort festlegen.

Die Action-Methode PostFlug in Listing 3 veranschaulicht dies. Sie greift über Request auf die übersendeten Kopfzeilen zu, um die benutzerdefinierte Kopfzeile X-API-Version auszulesen. Existiert sie und weist sie nicht die erwartete Versionsnummer auf, löst sie eine Ausnahme aus. Auf diese Weise verhindert sie, dass sich der Aufrufer an eine falsche Version einer Web-API wendet.

Anschließend speichert sie den übersendeten Flug und legt über die Eigenschaft Response den Statuscode der Antwort auf 201 fest. Dieser Statuscode gibt Auskunft darüber, dass der Webserver eine Ressource angelegt hat. Zusätzlich hinterlegt PostFlug für die Antwort eine Kopfzeile Location, die den URL dieser neuen Ressource widerspiegelt. Um diese nicht hardkodiert festlegen zu müssen, stützt sich PostFlight auf ein Hilfsobjekt des Typs IUrlHelper, das sich in der geerbten Eigenschaft Url befindet. Dessen Methode Action liefert den URL für eine bestimmte Action-Methode. Der Name der gewünschten Action-Methode sowie die Routing-Parameter finden sich in den übergebenen Parametern wieder. Letztere übergibt das betrachtete Beispiel als anonymes Objekt. Die Methode Action geht standardmäßig davon aus, dass sich die angeführte Action-Methode im aktuellen Controller befindet. Ist dem nicht so, kann der Aufrufer über eine weitere Überladung den Namen des Controllers – wie üblich ohne Endung Controller – angeben.

 [HttpPost]
public Flug PostFlug([FromBody]Flug flug)
{

  const string API_VERSION_HEADER = "X-API-Version";
  const string CURRENT_API_VERSION = "1.1";

  if (Request.Headers.ContainsKey(API_VERSION_HEADER) 
    && Request.Headers[API_VERSION_HEADER] != CURRENT_API_VERSION)
  {
    throw new Exception(
      "Wrong API-Version. Expected: " 
      + CURRENT_API_VERSION);
  }

  flug.FlugId = fluege.Max(f => f.FlugId) + 1;
  fluege.Add(flug);

  var location = Url.Action("GetById", new { id = flug.FlugId }
  // var location = Url.RouteUrl("FlugById", new { id = flug.FlugId });

  Response.Headers["Location"] = location;
  Response.StatusCode = 201;

  return flug;
}

Eine Alternative zur Methode Action von IUrlHelpers ist die Methode RouteUrl, deren Einsatz der Kommentar in Listing 3 andeutet. Statt des Namens einer Action-Methode nimmt sie den Namen einer Route entgegen. Die übergebenen Routing-Parameter setzt sie in die Platzhalter des URL-Templates dieser Route ein. Damit das möglich ist, muss der Entwickler die einzelnen Routen mit einem Namen versehen. Hierzu nutzt er beim Einsatz des Attribut-basierten Routings die Eigenschaft Name, die die Attribute HttpGet, HttpPost, HttpPatch, HttpPut, HttpDelete und AcceptVerbs anbietet:

 [HttpGet("{id:int}", Name = "FlugById")]
public Flug GetById(int id) { [...] }

Antworten über ActionResult beeinflussen

Will der Entwickler verhindern, dass er immer wieder dieselben Eigenschaften des Response-Objektes setzen muss, kann er diese Aufgaben auch in ein ActionResult auslagern. Dabei handelt es sich um eine Klasse, die das Interface IActionResult implementiert. Dieses Interface gibt eine asynchrone Methode ExecuteResultAsync vor. Liefert eine Action-Methode eine Implementierung von IActionResult retour, bringt MVC 6 ExecuteResultAsync zur Ausführung. Die Aufgabe dieser Methode ist es, die Antwortnachricht über das Response-Objekt zu definieren. Dazu kann sie die Nutzdaten ebenso setzen, wie den Statuscode oder Kopfzeilen.

Ein Beispiel für ein ActionResult findet sich in Listing 4. Anstatt das Interface IActionResult direkt zu implementieren, erbt es von der Basisklasse ActionResult, die zum einen IActionResult implementiert und zum anderen neben der asynchronen Methode ExecuteResultAsync ein synchrones Gegenstück mit dem Namen ExecuteResult aufweist (Abb. 1). Da ExecuteResultAsync an ExecuteResult delegiert, reicht es, diese Methode zu implementieren, wenn keine asynchronen Aufgaben zu erledigen sind. Ansonsten ist lediglich ExecuteResultAsync mit Leben zu erfüllen.

Abb. 1: ActionResult

Abb. 1: ActionResult

Das ApiResult in Listing 4 nimmt einen Wert für die Kopfzeile Location sowie einen Statuscode über Eigenschaften entgegen. Die Methode ExecuteResult reicht diese Werte an das Response-Objekt weiter. MVC übergibt dieser einen ActionContext, der Informationen über die aktuelle Action-Methode aufweist. Dazu gehören Daten über den Controller aber auch der Name der Action-Methode. Über ihre Eigenschaft HttpContext.Response gewährt sie Zugriff auf das benötigte Response-Objekt. Analog dazu könnte der Entwickler über HttpContext.Request auf das aktuelle Request-Objekt zugreifen.

Listing 4
public class ApiResult : ActionResult
{
  public string Location { get; set; }
  public int StatusCode { get; set; }

  public override void ExecuteResult(ActionContext context)
  {
    var response = context.HttpContext.Response;
    response.StatusCode = this.StatusCode;

    if (string.IsNullOrEmpty(this.Location))
    response.Headers["Location"] = this.Location;
  }

}

Um die zurückgelieferten Nutzdaten festzulegen, verwendet der Entwickler die Eigenschaft Response.Body, die auf einen Stream verweist. Alternativ dazu kann er von ActionResult-Derivaten ableiten, die diese Aufgabe bereits erledigen. Ein Beispiel dafür findet sich in Listing 5. Die hier gezeigte Klasse ApiResultWithBody erbt von ObjectResult. Dabei handelt es sich um ein ActionResult, das ein Objekt unter Verwendung eines Formatters serialisiert und im Rahmen der Nutzdaten an den Aufrufer sendet. Wie im vorherigen Beispiel nimmt auch ApiResultWithBody einen Wert für die Kopfzeile Location entgegen. Die Eigenschaft StatusCode erbt sie hingegen von ObjectResult. Der Konstruktor nimmt das zu serialisierende Objekt entgegen und reicht es an den Konstruktor der Basisklasse weiter.

Da ObjectResult seine Arbeit auf asynchrone Weise erledigt, ist auch die Methode ExecuteResultAsync zu überschreiben. Sie setzt die Kopfzeile Location und delegiert danach an die Basisimplementierung, die unter anderem den Statuscode festlegt und das über den Konstruktor definierte Objekt in serialisierter Form der Eigenschaft Body des Response-Objektes übergibt.

 public class ApiResultWithBody : ObjectResult
{
  public string Location { get; set; }

  public ApiResultWithBody(string value) : base(value)
  {
  }

  public override Task ExecuteResultAsync(ActionContext context)
  {
    var response = context.HttpContext.Response;

    if (string.IsNullOrEmpty(this.Location)) 
    response.Headers["Location"] = this.Location;

    return base.ExecuteResultAsync(context);
  }
}

Ein Beispiel für die Nutzung eines ActionResults findet sich in Listing 6. Es zeigt eine Variante der weiter oben behandelten Action-Methode PostFlug, die ein Objekt des Typs IActionResult retourniert. Nach getaner Arbeit instanziiert sie eine Instanz von ApiResultWithBody, die den erzeugten Flug über den Konstruktor sowie den Statuscode 201 und einen Wert für die Kopfzeile Location über Eigenschaften erhält. Diese Instanz liefert sie zurück.

 Listing 6
[HttpPost]
public IActionResult PostFlug([FromBody]Flug flug)
{
  flug.FlugId = fluege.Max(f => f.FlugId) + 1;
  fluege.Add(flug);

  return new ApiResultWithBody(flug)
  {
    Location = Url.Action("GetById", new { id = flug.FlugId }),
    StatusCode = 201
  };
}

ActionResult-Derivate

Der aktuelle Quellcode von ASP.NET MVC 6 unter GitHub lässt vermuten, dass die finale Version einige ActionResult-Derivate für den Einsatz mit Web-APIs beinhalten wird, sodass der Entwickler nicht gezwungen ist, eigene Implementierungen für Fälle wie den hier betrachteten bereitzustellen.

Der Einsatz von ActionResults ist unter anderem dann nützlich, wenn sich erst im Rahmen der Ausführung einer Action-Methode herausstellt, welche Art von Daten sie über die Nutzdaten retourniert. Liegt beispielsweise ein Validierungsfehler vor, könnte die hier betrachtete Action-Methode den Statuscode 400 (Bad Request) zusammen mit einem Objekt, das die Validierungsfehler beschreibt, retournieren. War die Validierung hingegen erfolgreich, könnte sie den Statuscode 201 (Created) inklusive des gespeicherten Flugs zurückliefern

Fazit und Ausblick

Während in der Vergangenheit mit ASP.NET MVC und ASP.NET Web-API zwei sehr ähnliche Frameworks nebeneinander existierten, findet mit ASP.NET MVC 6 eine Konsolidierung statt. Diese sieht vor, dass Web-API in MVC 6 aufgeht und MVC 6 somit sowohl für die Erstellung von Webanwendungen als auch für die Kreierung von Web-APIs verwendet wird. Diese Konsolidierung gestaltet sich aufgrund des ähnlichen Aufbaus der beiden Frameworks auf dem ersten Blick einfach. Bei genauerer Betrachtung fällt hingegen auf, dass der Teufel, wie so häufig, im Detail steckt, und sich Web-API-Entwickler nun an die Konventionen von MVC gewöhnen müssen. Dies ist der Preis für den Abbau jener technischen Schulden, die in der Vergangenheit durch das Zulassen von Mehrgleisigkeiten entstanden sind. Um den damit einhergehenden Aufwand zu reduzieren, bietet Microsoft mit dem WebApiCompatShim eine Komponente, die MVC 6 veranlasst, sich ähnlich wie Web-API zu verhalten.

Dieser erste Artikel hat die grundlegenden Möglichkeiten zur Erstellung von Web-APIs mit MVC 6 betrachtet. Der zweite Teil behandelt hingegen weiterführende Themen, die bei der Erstellung von Web-APIs zu beachten sind. Dazu gehört beispielsweise der Umgang mit Formattern, die für die (De-)Serialisierung von Objekten sowie das Protokollieren von Aufrufen verantwortlich sind.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -