예제 #1
0
        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);
            }
        }
예제 #2
0
        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));
        }
예제 #6
0
        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);
            }
        }