public void DoWork(IRequest request) { if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry) { throw new RequestException("Atom entry content type expected"); } if (!String.IsNullOrEmpty(_requestContext.ResourceKey)) { throw new RequestException("Please use resource url"); } // read entry from stream SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, ResourceKindHelpers.GetPayloadType(_requestContext.ResourceKind)); IEntityWrapper wrapper = EntityWrapperFactory.Create(_requestContext.ResourceKind, _requestContext); Document document = wrapper.GetTransformedDocument(entry.Payload, entry.SyncLinks); if (!String.IsNullOrEmpty(document.Id)) { throw new RequestException("Entity alredy exists"); } // Add Document SdataTransactionResult sdTrResult = wrapper.Add(entry.Payload, entry.SyncLinks); if (sdTrResult == null) { throw new RequestException("Entity does not exists"); //????? } if ((sdTrResult.HttpStatus == System.Net.HttpStatusCode.OK) || (sdTrResult.HttpStatus == System.Net.HttpStatusCode.Created)) { // store correlation SyncFeedEntry responseEntry = wrapper.GetFeedEntry(sdTrResult.LocalId); SyncFeed feed = new SyncFeed(); feed.FeedType = FeedType.ResourceEntry; feed.Entries.Add(responseEntry); request.Response.StatusCode = System.Net.HttpStatusCode.Created; request.Response.Serializer = new SyncFeedSerializer(); request.Response.Feed = feed; request.Response.Protocol.SendUnknownResponseHeader("Location", responseEntry.Id); request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry; } else { throw new RequestException(sdTrResult.HttpMessage); } }
public void DoWork(IRequest request) { // only atom entry supported!!! if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry) { throw new RequestException("Atom entry content type expected"); } // deserialize the request stream to a SyncFeedEntry SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, typeof(SyncDigestPayload)); if (null == entry.Linked) { throw new RequestException("Invalid content: element 'linked' missing"); } // We check for equality of the urls of the request url and // in the linked element up to the resourceKind. string requestEndpointUrl = _requestContext.OriginEndPoint; RequestContext entryResourceAsRequestContext = new RequestContext(new Sage.Common.Syndication.SDataUri(entry.Linked.Resource)); // TODO: not really nice here. string linkedResourceUrl = entryResourceAsRequestContext.OriginEndPoint; if (!string.Equals(requestEndpointUrl, linkedResourceUrl, StringComparison.InvariantCultureIgnoreCase)) { throw new RequestException("Request url and linked entry resource not matching."); } string resourceKindName = _requestContext.ResourceKind.ToString(); Guid currentUuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(_requestContext.ResourceKey); Guid newUuid = entry.Linked.Uuid; string newLocalId = entryResourceAsRequestContext.SdataUri.CollectionPredicate; // update the correlation entry in the sync store. // if the uuid should be updated we have to remove the current correlation and then add a new one. // otherwise we update the current correlation. ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext); // create the target correlation ResSyncInfo targetResSyncInfo = new ResSyncInfo(newUuid, requestEndpointUrl, 0, string.Empty, DateTime.Now); CorrelatedResSyncInfo targetInfo = new CorrelatedResSyncInfo(newLocalId, targetResSyncInfo); if (currentUuid == newUuid) { correlatedResSyncInfoStore.Update(resourceKindName, targetInfo); } else { correlatedResSyncInfoStore.Delete(resourceKindName, currentUuid); correlatedResSyncInfoStore.Add(resourceKindName, targetInfo); } // create response SyncFeed feed = new SyncFeed(); feed.FeedType = FeedType.LinkedSingle; // create entry SyncFeedEntry responseEntry = new SyncFeedEntry(); responseEntry.Id = FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, targetInfo.ResSyncInfo.Uuid); responseEntry.Title = FeedMetadataHelpers.BuildLinkedEntryTitle(_requestContext, targetInfo.ResSyncInfo.Uuid); LinkedElement linkedElement = new LinkedElement(); linkedElement.Resource = FeedMetadataHelpers.BuildEntryResourceUrl(_requestContext, targetInfo.LocalId); linkedElement.Uuid = targetInfo.ResSyncInfo.Uuid; responseEntry.Linked = linkedElement; feed.Entries.Add(responseEntry); request.Response.Serializer = new SyncFeedSerializer(); request.Response.Feed = (IFeed)feed; request.Response.ContentType = MediaType.AtomEntry; }
//private NorthwindConfig _config; #endregion #region IRequestProcess Members public void DoWork(IRequest request) { // If an asyncState object already exists, an exception is thrown as the performer only accepts // one call after each other. The Request receiver has to manage a queued execution. // Before calling the performers execution implementation method a new AsyncState object is created // and set to an initial tracking state. lock (_asyncStateObj) { if (null != _asyncStateObj.Tracking) { throw new InvalidOperationException("The performer cannot be executed because it is already running."); } SyncTracking tracking = new SyncTracking(); tracking.ElapsedSeconds = 1; tracking.Phase = TrackingPhase.INIT; tracking.PhaseDetail = "Tracking Id was: " + _requestContext.TrackingId.ToString(); tracking.PollingMillis = 100; tracking.RemainingSeconds = 100; _asyncStateObj.Tracking = tracking; } // *** Initialization for the async execution *** // - Read SyncDigest from request stream. // - Read trackingId from request URL //// Load input stream (throws RequestException if it fails.) //XmlDocument xmlInputDoc; //InputStreamHelpers.Get(request, out xmlInputDoc); //// load syncDigest info from input stream of the request //SyncDigestInfo syncDigestInfo = SyncDigestInfoHelpers.Load(xmlInputDoc); SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, typeof(SyncDigestPayload)); if (entry.Payload == null) { throw new RequestException("Invalid Content"); } SyncFeedDigest syncDigestInfo = ((SyncDigestPayload)entry.Payload).Digest; // convert tracking ID from request to type Guid string strTrackingId = request.Uri.TrackingID; if (String.IsNullOrEmpty(strTrackingId)) { throw new RequestException("TrackingId is missing"); } GuidConverter converter = new GuidConverter(); this.TrackingId = (Guid)converter.ConvertFrom(strTrackingId); // *** Do work asynchronously *** _asyncPerformer = new InternalAsyncPerformer(this); _asyncPerformer.DoWork(_requestContext.Config, syncDigestInfo); // *** set the tracking to the request response *** this.GetTrackingState(request); }
public void DoWork(IRequest request) { //// check for resource kind existence and supported types //if (_requestContext.ResourceKind == SupportedResourceKinds.None) // throw new RequestException("Invalid request: The service {0} is a resource based service."); // if request was done in the context of a resource kind -> check for supported resourceKinds if (_requestContext.ResourceKind != SupportedResourceKinds.None) { if (!(_requestContext.ResourceKind == SupportedResourceKinds.salesOrders || _requestContext.ResourceKind == SupportedResourceKinds.salesOrderLines)) { throw new RequestException("Invalid request: The service {0} is only supported by salesOrders and salesOrderLines."); } } // read entry from stream SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, typeof(ComputePriceRequestPayload)); // underlying resources for price computing computePriceRequesttype computePriceRequest; CommodityIdentity[] productIds; // will contain local ids of the commodity referenced by line items. // Could contain empty items if commodity id could not be found. // compute price computePriceResponsetype computePriceResponse; if (null == entry.Payload) { throw new RequestException("Invalid Xml input stream. Could not parse the payload."); } computePriceRequest = ((ComputePriceRequestPayload)entry.Payload).ComputePriceRequest; #region Trading Account (discounted) // get the undelying trading account // is null if request is not in the context of an account. // if no account found means that the account exists in CRM only // and has not yet been linked with ERP. ERP could treat the account as a // prospect account and generate a price for the account, or if this is not // possible it could return an error. #endregion #region PricingDocument (only salesOrder suppported) // document associated with this pricing request (e.g. the Sales Order, Quotation, Purchase Order number). // could be of any type of enumeration "pricingDocumenttype" // if no document exists the request is not in the context of a document like order, quote, etc. // TODO: Get the associated document to find out the context of the request. // Validate document type // here: only salesOrder supported // removed to avoid possible errors (OK as this is only an example project) //if (computePriceRequest.pricingDocumentType != pricingDocumenttype.salesOrder) // throw new RequestException("Invalid document type in element 'pricingDocumentType' defined. Only salesOrder supported."); #endregion #region Commodities (for each document lines) // Get Commodity local ids used on the associated document lines. // (the array returned is always of the same size as the number of document lines in the request payload. // If a commodity local id could not be found in feed entry the array item will be null. productIds = this.GetCommodityIds(entry); // (never returns null, but could return an empty array) #endregion // compute price PricingServices pricingServices = new PricingServices(_requestContext.Config); if (_requestContext.ResourceKind == SupportedResourceKinds.salesOrders || _requestContext.ResourceKind == SupportedResourceKinds.None) { computePriceResponse = pricingServices.ComputePrice(computePriceRequest, productIds, false); } else { computePriceResponse = pricingServices.ComputePrice(computePriceRequest, productIds, true); } // create response feed this.BuildResponseFeed(ref request, computePriceResponse); //this.BuildResponseFeed(ref request, cpr); }
public void DoWork(IRequest request) { // only atom entry supported!!! if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry) { throw new RequestException("Atom entry content type expected"); } // deserialize the request stream to a SyncFeedEntry SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, typeof(SyncDigestPayload)); if (null == entry.Linked) { throw new RequestException("Invalid content: element 'linked' missing"); } // Parse the resource url to get the local id. // Additionally we check for equality of the urls of the request url and // in the linked element up to the resourceKind. string requestEndpointUrl = _requestContext.OriginEndPoint; RequestContext entryResourceAsRequestContext = new RequestContext(new Sage.Common.Syndication.SDataUri(entry.Linked.Resource)); // TODO: not really nice here. string linkedResourceUrl = entryResourceAsRequestContext.OriginEndPoint; if (!string.Equals(requestEndpointUrl, linkedResourceUrl, StringComparison.InvariantCultureIgnoreCase)) { throw new RequestException("Request url and linked entry resource not matching."); } string resourceKindName = _requestContext.ResourceKind.ToString(); string localId = entryResourceAsRequestContext.SdataUri.CollectionPredicate; Guid uuid = entry.Linked.Uuid; // store a new correlation entry to the sync store ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext); ResSyncInfo newResSyncInfo = new ResSyncInfo(uuid, requestEndpointUrl, 0, string.Empty, DateTime.Now); CorrelatedResSyncInfo newInfo = new CorrelatedResSyncInfo(localId, newResSyncInfo); correlatedResSyncInfoStore.Add(resourceKindName, newInfo); // Set the response values SyncFeed feed = new SyncFeed(); feed.FeedType = FeedType.LinkedSingle; SyncFeedEntry feedEntry = new SyncFeedEntry(); feedEntry.Title = FeedMetadataHelpers.BuildLinkedEntryTitle(_requestContext, uuid); feedEntry.Id = FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, uuid); feedEntry.Updated = newInfo.ResSyncInfo.ModifiedStamp; feedEntry.Published = newInfo.ResSyncInfo.ModifiedStamp; feedEntry.Linked = entry.Linked; feed.Entries.Add(feedEntry); request.Response.Serializer = new SyncFeedSerializer(); request.Response.Feed = (IFeed)feed; request.Response.ContentType = MediaType.AtomEntry; request.Response.StatusCode = System.Net.HttpStatusCode.Created; request.Response.Protocol.SendUnknownResponseHeader("location", FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, uuid)); }
public void DoWork(IRequest request) { if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry) { throw new RequestException("Atom entry content type expected"); } if (String.IsNullOrEmpty(_requestContext.ResourceKey)) { throw new RequestException("Please use single resource url"); } //SupportedResourceKinds resKind = _requestContext.ResourceKind; //switch (resKind) //{ // case SupportedResourceKinds.tradingAccounts: // case SupportedResourceKinds.contacts: // case SupportedResourceKinds.phoneNumbers: // case SupportedResourceKinds.postalAddresses: // break; // default: // throw new RequestException("Put is not Supported for requested resource"); //} // read entry from stream SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, ResourceKindHelpers.GetPayloadType(_requestContext.ResourceKind)); IEntityWrapper wrapper = EntityWrapperFactory.Create(_requestContext.ResourceKind, _requestContext); Token emptyToken = new Token(); Identity identity = wrapper.GetIdentity(_requestContext.ResourceKey); Document originalDocument = wrapper.Entity.GetDocument(identity, emptyToken, _requestContext.Config); if (originalDocument.LogState == LogState.Deleted) { throw new RequestException("Entity does not exists"); } entry.Payload.LocalID = _requestContext.ResourceKey; SdataTransactionResult sdTrResult = wrapper.Update(entry.Payload, entry.SyncLinks); if (sdTrResult == null) { SyncFeedEntry responseEntry = wrapper.GetFeedEntry(_requestContext.ResourceKey); SyncFeed feed = new SyncFeed(); feed.FeedType = FeedType.ResourceEntry; feed.Entries.Add(responseEntry); request.Response.Serializer = new SyncFeedSerializer(); request.Response.Feed = feed; request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry; } else if (sdTrResult.HttpStatus == System.Net.HttpStatusCode.OK) { SyncFeedEntry responseEntry = wrapper.GetFeedEntry(_requestContext.ResourceKey); SyncFeed feed = new SyncFeed(); feed.FeedType = FeedType.ResourceEntry; feed.Entries.Add(responseEntry); request.Response.Serializer = new SyncFeedSerializer(); request.Response.Feed = feed; request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry; } else { throw new RequestException(sdTrResult.HttpMessage); } }