2016-10-25 2 views
0

Ich habe eine übergeordnete (Bestellung) und untergeordnete (OrderDetail), wobei Bestellung bereits in der Datenbank vorhanden ist und OrderDetail auch in der Datenbank vorhanden ist.
Alles, was ich wirklich tun möchte, ist das Hinzufügen eines anderen OrderDetail-Datensatzes, der an den Auftrag gebunden ist.OData V4-Client, der untergeordnete Entität hinzufügt

Ich habe mehrere Pfade hinunter und ich bin nicht einmal sicher, was der richtige Pfad ist.
Lassen Sie uns einige Annahmen machen, dass die Navigation zwischen diesen bereits funktioniert.
Ich kann $ expand = OrderDetails in Ordnung und ich kann auch Orders (1)/OrderDetails gut machen und das Gegenteil von OrderDetails tun.

Basierend auf dieser Updating the Data Service, alles, was ich tun muss, ist AddRelatedObject aufrufen und dann das Objekt der OrderDetails-Auflistung hinzufügen.

// Add the new item with a link to the related Order 
context.AddRelatedObject(order, "OrderDetails", newOrderDetail); 
// Add the new order detail to the collection 
order.Order_Details.Add(newOrderDetail); 
newOrderDetail.Order = order; 

Scheint einfach genug.
Wenn ich jedoch context.SaveChanges (SaveChangesOptions.ReplaceOnUpdate) ausführen, wird ein Fehler ausgelöst.

{ "Fehler": { "Code": "", "message": "Nein HTTP-Ressource wurde gefunden, dass der Anforderungs-URI übereinstimmt 'http://localhost/Test/odata/Orders(1)/OrderDetails'", "innererror.": { "Message":“ . ":"“, "Stack Trace": keine Routing-Konvention wurde eine Aktion auszuwählen, die für den OData Pfad mit Vorlage '~/EntitySet/key/Navigation' "" type gefunden ""}}}

Aber Wenn ich zur angegebenen URL navigiere, werden Daten angezeigt.
Zeit für Fiddler.
In Fiddler kann ich sehen, das ist ein POST an die URL und kein GET.
Welche es sollte ein POST sein, aber nicht auf die URL aufgeführt.
Die POST/OData/Orderdetails

sein sollte

Runde 2

// Add the new item with a link to the related Order 
context.AttachTo("OrderDetails", newOrderDetail); 
// Add a link between Order and the new OrderDetail 
context.AddLink(order, "OrderDetails", newOrderDetail); 
// Add the new order detail to the collection 
order.Order_Details.Add(newOrderDetail); 
newOrderDetail.Order = order; 

Noch ein POST mit einem Fehler, aber die URL ist etwas anders und die entsandte json hat nur „/ OData/Orderdetail (0) "Es hat jetzt auch" $ ref ".

{ "Fehler": { "Code": "", "message": "Keine HTTP-Ressource wurde gefunden, dass die Anforderungs-URI 'http://localhost/Test/odata/Orders(1)/OrderDetails/ $ ref' passt", "innererror": { "message" : "Es wurde keine Routingkonvention gefunden, um eine Aktion für den OData-Pfad mit der Vorlage '~/entityset/key/navigation/$ ref' auszuwählen.", "Type": "", "stacktrace": ""}}}

Nun führte mich eine schnelle Websuche zu diesem Artikel Entity Relations in OData v4 Using ASP.NET Web API 2.2
Dieser Artikel sagt, ich muss eine "CreateRef" in der Orders-Controller hinzufügen.
Ich habe eine "CreateRef" in der Bestellung Controller und sicher genug, es wird aufgerufen, aber der Artikel geht davon aus, dass die OrderDetail in der Datenbank vorhanden ist.
Das json OrderDetail-Objekt wird nicht gebucht.

Runde 3

// Add the new item with a link to the related Order 
context.AttachTo("OrderDetails", newOrderDetail); 
// Attach a link between Order and the new OrderDetail 
context.AttachLink(order, "OrderDetails", newOrderDetail); 
// Add the new order detail to the collection 
order.Order_Details.Add(newOrderDetail); 
newOrderDetail.Order = order; 

Nun scheint dies viel besser.
Kein Fehler, aber es hat nicht vollständig funktioniert.
Es wurde ein PUT an die/odata/OrderDetails (0) gesendet und es wurde das json OrderDetail Objekt gesendet, ABER das sollte ein POST kein PUT sein.

Ich fühle, dass ich so nah bin, aber ich kann nicht scheinen, herauszufinden, wie es richtig funktioniert.

Irgendwelche Ideen?

Antwort

0

Nach Versuch und Irrtum habe ich etwas gefunden, das funktioniert.

// create a new order detail 
OrderDetail newOrderDetail = new OrderDetail(); 
// set the orderID on the new order detail 
newOrderDetail.OrderID = order.ID; 
// add the order back as a link on the order detail 
newOrderDetail.Order = order; 
// add the order detail to the order detail collection on the order 
order.OrderDetails.Add(newOrderDetail); 
// add the order detail to the context 
context.AddToOrderDetail(newOrderDetail); 
// now update context for the order 
context.UpdateObject(order); 
// now save 
context.SaveChanges(); 
0

Ich hatte das gleiche Problem und fand die Lösung heute.

Werfen Sie einen Blick auf http://aspnetwebstack.codeplex.com/discussions/457028:

Es gibt keine eingebaute Konvention POST-Anfragen zu ~/EntitySet (key)/Navigation zu handhaben. Du musst einen selbst bauen. Schauen Sie sich hierzu a sample code an.

Sie müssen zuerst eine EntitySetRoutingConvention erstellen:

public class CreateNavigationPropertyRoutingConvention : EntitySetRoutingConvention 
{ 
    public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap) 
    { 
     if (odataPath.PathTemplate == "~/entityset/key/navigation" && controllerContext.Request.Method == HttpMethod.Post) 
     { 
      IEdmNavigationProperty navigationProperty = (odataPath.Segments[2] as NavigationPathSegment).NavigationProperty; 
      controllerContext.RouteData.Values["key"] = (odataPath.Segments[1] as KeyValuePathSegment).Value; // set the key for model binding. 
      return "PostTo" + navigationProperty.Name; 
     } 

     return null; 
    } 
} 

Dann haben Sie es in WebApiConfig.Register registrieren:

var routingConventions = ODataRoutingConventions.CreateDefault(); 
routingConventions.Insert(0, new CreateNavigationPropertyRoutingConvention()); 
server.Configuration.Routes.MapODataRoute("odata", "", GetEdmModel(), new DefaultODataPathHandler(), routingConventions); 

Bitte beachten Sie diese Probe für OData v3 ist aber sein kann leicht in v4 konvertiert.

Dann müssen Sie nur Ihr übergeordnetes Objekt zum Kontext hinzufügen und AddRelatedObject für alle untergeordneten Elemente verwenden. Ihre Anfrage wird an dieser Leere in Ihrem ParentController senden werden:

public HttpResponseMessage PostToOrders([FromODataUri] int key, Order order) 
    { 
     // create order. 
     return Request.CreateResponse(HttpStatusCode.Created, order); 
    } 
+0

Danke für die Informationen, aber nach Versuch und Irrtum konnte ich die Antwort finden. Es war ein Problem auf der Client-Seite in der Art, wie ich versuchte, das Kind dem Elternteil hinzuzufügen. – goroth

Verwandte Themen