private BeaconEntity TrackPageEvent(string id, SpoofedHttpRequestBase spoofedRequest, PageEventType eventType, string page, string contactId, string data = null, string dataKey = null, IDictionary <string, string> extras = null, string monetaryValue = "0") { return(this.ExecuteTrackingRequest(string.Format("[PageVisit] : Page = {0} : Event = {1} : CID = {2}", page, eventType, contactId), delegate { if (string.IsNullOrWhiteSpace(id)) { throw HttpExceptionHelper.BadRequest("Bad Request", "No event identifier was specified."); } PageEventParameters pageEventParameters; if (id.IsGuid()) { pageEventParameters = new PageEventParameters(spoofedRequest.Url, new ID(id), eventType, contactId); } else { pageEventParameters = new PageEventParameters(spoofedRequest.Url, id, eventType, contactId); } pageEventParameters.Data = data; pageEventParameters.DataKey = dataKey; pageEventParameters.Extras = extras; if (eventType == PageEventType.Outcome) { decimal monetaryValue2; if (!decimal.TryParse(monetaryValue, out monetaryValue2)) { throw HttpExceptionHelper.BadRequest("Bad Request", "The outcome monetary value is invalid."); } pageEventParameters.MonetaryValue = monetaryValue2; } return this.trackingManager.TrackPageEvent(this.httpContextBase.Request, spoofedRequest, this.httpContextBase.Response, pageEventParameters); })); }
/// <summary> /// The initialize template tables. /// </summary> /// <exception cref="ValidationException"> /// The workflow is invalid /// </exception> private void InitializeTemplateTables() { try { // Cache definitions so we don't run CacheMetadata more than once. if (!UriTemplateTables.ContainsKey(this.Activity)) { WorkflowInspectionServices.CacheMetadata(this.Activity); UriTemplateTables.Add(this.Activity, new List <UriTemplateTable>()); foreach (var uriTemplateTable in this.BaseAddresses.Select(baseAddress => new UriTemplateTable(baseAddress))) { UriTemplateTables[this.Activity].Add(uriTemplateTable); this.LocateHttpReceiveActivities(this.Activity, uriTemplateTable); // No UriTemplates in this activity if (uriTemplateTable.KeyValuePairs.Count == 0) { throw new ValidationException( "Activity must contain at least one HttpReceive activity with a valid Uri template"); } } } } #if DEBUG catch (Exception ex) { HttpExceptionHelper.WriteThread(ex.Message); throw; } #endif }
/// <summary> /// The wait for unload. /// </summary> /// <param name="timeout"> /// The timeout. /// </param> /// <exception cref="TimeoutException"> /// The unload event did not occur within the timeout /// </exception> public void WaitForUnload(TimeSpan timeout) { if (!this.unloadEvent.WaitOne(timeout)) { HttpExceptionHelper.WriteThread( "Timeout waiting for workflow to unload"); throw new TimeoutException(); } }
/// <summary> /// The run until bookmark. /// </summary> /// <param name="bookmarkName"> /// The bookmark name. /// </param> /// <exception cref="HttpResponseException"> /// Timeout while waiting for bookmark /// </exception> private void RunUntilBookmark(string bookmarkName) { this.pendingBookmark = bookmarkName; this.workflowApplication.Run(); if (!this.protocolEvent.WaitOne(this.serviceHost.WorkflowTimeout)) { throw HttpExceptionHelper.CreateResponseException( HttpStatusCode.InternalServerError, "Timeout waiting for idle with bookmark {0}", this.pendingBookmark); } }
public long MigrationNumber(string encodedBranch, MigrationType type) { var branch = HttpUtility.UrlDecode(encodedBranch); try { return(_provider.ReadMigrationNumber(branch, type)); } catch (Exception e) { Log.Error(e); throw HttpExceptionHelper.ServerError(e.Message); } }
/// <summary> /// The select matching receive activity. /// </summary> /// <returns> /// </returns> private HttpReceive SelectMatchingReceiveActivity() { var match = this.serviceHost.MatchSingle(this.Request); if (match == null) { HttpExceptionHelper.CreateResponseException( HttpStatusCode.NotFound, "No Http Receive activity found with Uri template matching Uri {0}", this.Request.RequestUri); } return(match != null ? (HttpReceive)match.Data : null); }
public string MigrationNumber(string encodedBranch, MigrationType type, long number) { var branch = HttpUtility.UrlDecode(encodedBranch); try { _provider.UpdateMigrationNumber(branch, type, number); } catch (Exception e) { Log.Error(e); throw HttpExceptionHelper.ServerError(e.Message); } return("ok"); }
/// <summary> /// The on idle. /// </summary> /// <param name="args"> /// The args. /// </param> private void OnIdle(WorkflowApplicationIdleEventArgs args) { HttpExceptionHelper.WriteThread( "OnWorkflowIdle waiting for bookmark {0} instance Id {1} with bookmarks {2}", this.pendingBookmark, args.InstanceId, args.BookmarksToDelimitedList()); this.Idle = true; if (args.ContainsBookmark(this.pendingBookmark)) { this.pendingBookmark = null; this.protocolEvent.Set(); } }
protected BeaconEntity ExecuteTrackingRequest(string requestInfo, Func <TrackingResult> implementation) { BeaconEntity result; try { string text; if (!this.TryGetSessionId(out text)) { throw HttpExceptionHelper.BadRequest("Bad Request", "Session could not be initialized with the details provided."); } TrackingResult trackingResult = implementation(); if (trackingResult == null) { throw HttpExceptionHelper.InternetServerError("Unexpected server error", "Tracking result could not be determined."); } if (trackingResult.ResultCode != TrackingResultCode.Success) { this.logger.Debug(string.Format("[FXM Tracking] [Failed] : Session = {0} : Code : {1} : Message : {2} : {3}", new object[] { text, trackingResult.ResultCode, trackingResult.Message, requestInfo }), null); throw HttpExceptionHelper.BadRequest(trackingResult.ResultCode.ToString(), trackingResult.Message); } this.logger.Debug((!trackingResult.DoNotTrack) ? string.Format("[FXM Tracking] : Session = {0} : {1}", text, requestInfo) : string.Format("[FXM Tracking] [DoNotTrack] : Session = {0} : {1}", text, requestInfo), null); BeaconEntity beaconEntity = (BeaconEntity)trackingResult; beaconEntity.SessionId = text; result = beaconEntity; } catch (HttpResponseException exception) { this.logger.Error(string.Format("[FXM Tracking] [Error] : {0}", requestInfo), exception, typeof(BeaconController)); throw; } catch (Exception ex) { this.logger.Error(string.Format("[FXM Tracking] [Error] : {0}", requestInfo), ex, typeof(BeaconController)); throw HttpExceptionHelper.InternetServerError("Unexpected server error", ex.Message); } return(result); }
protected SpoofedHttpRequestBase GetSpoofedRequest(string page, string referrer) { Uri url; if (string.IsNullOrWhiteSpace(page) || !Uri.TryCreate(page, UriKind.Absolute, out url)) { throw HttpExceptionHelper.BadRequest("Bad Request", "No valid page was specified."); } Uri urlReferrer = null; if (!string.IsNullOrEmpty(referrer) && !Uri.TryCreate(referrer, UriKind.RelativeOrAbsolute, out urlReferrer)) { throw HttpExceptionHelper.BadRequest("Bad Request", "An invalid referrer was specified."); } SpoofedHttpRequestBase spoofedHttpRequestBase = new SpoofedHttpRequestBase(this.httpContextBase.Request); spoofedHttpRequestBase.SetUrl(url); spoofedHttpRequestBase.SetUrlReferrer(urlReferrer); return(spoofedHttpRequestBase); }
/// <summary> /// The unload if idle. /// </summary> /// <param name="state"> /// The state. /// </param> private void UnloadIfIdle(object state) { if (this.idle) { HttpExceptionHelper.WriteThread( "Unloading Idle Instance {0} at {1}", this.workflowApplication.Id, DateTime.Now.ToString("mm:ss")); if (this.serviceHost.OnUnload != null) { // The host may decide it does not want to unload this instance. if (!this.serviceHost.OnUnload(this.workflowApplication)) { HttpExceptionHelper.WriteThread( "Host OnUnload returned false for Instance {0}", this.workflowApplication.Id); return; } } // Once unloaded you cannot use the instance again WorkflowApplicationCache.Remove(this.workflowApplication.Id); this.workflowApplication.Unload(); } }
public BeaconEntity StopTracking(string contactId = "", bool killContact = false, string endTime = "") { if (this.httpContextBase != null && this.httpContextBase.Session != null) { string arg; if (!this.TryGetSessionId(out arg)) { HttpExceptionHelper.InternetServerError("Unexpected server error", "Session could not be initialized."); } this.logger.Debug(string.Format("[StopTracking]: CID: {0} SID: {1}", contactId, arg), null); HttpRequestBase httpRequestBase = this.httpContextBase.Request; if (!base.Request.Headers.Referrer.Host.Equals(base.Request.RequestUri.Host)) { SpoofedHttpRequestBase spoofedHttpRequestBase = new SpoofedHttpRequestBase(this.httpContextBase.Request); spoofedHttpRequestBase.SetUrl(base.Request.Headers.Referrer); httpRequestBase = spoofedHttpRequestBase; IDomainMatcher domainMatcher; Language language; if (!this.trackingManager.DomainIsValid(httpRequestBase, out domainMatcher, out language)) { throw new HttpResponseException(HttpStatusCode.BadRequest); } TrackPageVisitArgs args = new TrackPageVisitArgs(this.sitecoreContext, this.trackerProvider, this.httpContextBase.Request, this.httpContextBase.Response, httpRequestBase, new PageVisitParameters(this.httpContextBase.Request.Url, null, contactId), domainMatcher, false); InitializeTrackingCookieProcessor initializeTrackingCookieProcessor = new InitializeTrackingCookieProcessor(); initializeTrackingCookieProcessor.Process(args); InitializeExternalTrackingProcessor initializeExternalTrackingProcessor = new InitializeExternalTrackingProcessor(); initializeExternalTrackingProcessor.Process(args); InitializeContextSiteProcessor initializeContextSiteProcessor = new InitializeContextSiteProcessor(); initializeContextSiteProcessor.Process(args); } else { Tracker.Initialize(); Tracker.Current.Session.SetClassification(0, 0, false); } if (!string.IsNullOrWhiteSpace(endTime)) { DateTime dateTime = DateTime.Parse(endTime, DateTimeFormatInfo.InvariantInfo); CurrentInteraction interaction = this.trackerProvider.Current.Interaction; Assert.IsNotNull(interaction, "interaction"); TimeSpan t = DateTime.UtcNow - DateUtil.ToUniversalTime(dateTime); interaction.EndDateTime = dateTime; interaction.StartDateTime -= t; Page[] pages = interaction.Pages; for (int i = 0; i < pages.Length; i++) { Page page = pages[i]; page.DateTime -= t; } } this.httpContextBase.Session.Abandon(); this.httpContextBase.Response.Cookies.Clear(); if (killContact) { DateTime expires = new DateTime(1979, 1, 1, 0, 0, 0, DateTimeKind.Utc); string[] allKeys = this.httpContextBase.Request.Cookies.AllKeys; for (int j = 0; j < allKeys.Length; j++) { string text = allKeys[j]; HttpCookie cookie = new HttpCookie(text) { Expires = expires, Value = string.Empty, Domain = this.httpContextBase.Request.Cookies.GetSafely(text).Domain }; this.httpContextBase.Response.Cookies.Add(cookie); } this.httpContextBase.Response.Cookies.Add(new HttpCookie("SC_ANALYTICS_GLOBAL_COOKIE") { Domain = "." + this.httpContextBase.Request.Url.Host, Value = string.Empty, Expires = expires }); } } return(new BeaconEntity { Id = "TBC", ContactId = string.Empty, SessionId = string.Empty, Url = string.Empty }); }
/// <summary> /// Delivers the Http message to the receive activity and waits until the receive is closed before returning /// </summary> /// <param name="bookmarkName"> /// The name of the bookmark to wait for /// </param> /// <param name="receive"> /// The HttpReceive activity to deliver to /// </param> private void DeliverMessage(string bookmarkName, HttpReceive receive) { HttpExceptionHelper.WriteThread( "Delivering message to HttpReceive activity {0} ID {1} \"{2}\"", bookmarkName, receive.Id, receive.DisplayName); var timeLeft = this.serviceHost.WorkflowTimeout; var retryMsecs = 10; while (timeLeft > TimeSpan.Zero) { // When resuming, the workflow might not be ready var result = this.workflowApplication.ResumeBookmark(bookmarkName, this); switch (result) { case BookmarkResumptionResult.Success: if (!this.responseEvent.WaitOne(timeLeft)) { throw HttpExceptionHelper.CreateResponseException( HttpStatusCode.InternalServerError, "Workflow timeout while waiting for response for {0}", bookmarkName); } // If the workflow terminated with an exception throw it if (this.terminationException != null) { throw this.terminationException; } return; case BookmarkResumptionResult.NotFound: throw HttpExceptionHelper.CreateResponseException( HttpStatusCode.InternalServerError, "Workflow was not waiting for bookmark {0}", bookmarkName); case BookmarkResumptionResult.NotReady: HttpExceptionHelper.WriteThread( "Workflow Instance {0} was not ready to receive bookmark {1} retrying...", bookmarkName, this.workflowApplication.Id); // The workflow was not ready to receive the resumption Thread.Sleep(retryMsecs); timeLeft = timeLeft - TimeSpan.FromMilliseconds(retryMsecs); retryMsecs = retryMsecs * 2; break; default: throw new ArgumentOutOfRangeException(); } } throw HttpExceptionHelper.CreateResponseException( HttpStatusCode.InternalServerError, "Unable to deliver message to Workflow ID {0} for bookmark {1}", this.workflowApplication.Id, bookmarkName); }
public HttpResponseMessage InvokeWorkflow() { #if DEBUG this.testName = this.Request.Headers.GetHeaderValue("TestName"); this.testInfo = this.Request.Headers.GetHeaderValue("TestInfo"); HttpExceptionHelper.WriteThread( "HttpResponseMessage InvokeWorkflow() message received {0} {1} Test: \"{2}\" Info:{3}", this.Request.Method, this.Request.RequestUri, this.testName, this.testInfo); #endif // Step 1 - locate a receive activity that matches the Uri template // This will throw if no matching activity is found var receive = this.SelectMatchingReceiveActivity(); if (receive == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } // Step 2 - Load or Create a workflow instance this.LoadOrCreateWorkflowInstance(); HttpExceptionHelper.WriteThread( "Trying to Lock instance {0} {1} {2} Test: \"{3}\" Info:{4}", this.workflowApplication.Id, this.Request.Method, this.Request.RequestUri, this.testName, this.testInfo); if (!Monitor.TryEnter(this.workflowApplication, this.ServiceHost.WorkflowTimeout)) { throw HttpExceptionHelper.CreateResponseException( HttpStatusCode.InternalServerError, "Timeout waiting for lock on instance {0}", this.workflowApplication.Id); } try { HttpExceptionHelper.WriteThread( "Successfully Locked instance {0} {1} {2} Test: \"{3}\" Info:{4}", this.workflowApplication.Id, this.Request.Method, this.Request.RequestUri, this.testName, this.testInfo); // There may be a bookmark pending for this receive activity var bookmarkName = receive.GetBookmarkName(this.serviceHost.GetMatchingBaseAddress(this.Request.RequestUri)); // If the instance does not have the bookmark, create and run it if (!this.workflowApplication.ContainsBookmark(bookmarkName)) { // This will run the workflow until it becomes idle with the named bookmark // Or it aborts, times out or completes this.RunUntilBookmark(bookmarkName); } // Deliver the message to the receive activity by resuming the bookmark this.DeliverMessage(bookmarkName, receive); // The receive activity may or may not set a response HttpExceptionHelper.WriteThread("Returning response {0}", this.Response); // TODO: This makes IQueryable not work - can we return a response as an object? // If we do return an object, what if it is already an HttpResponse? return(this.Response); } finally { HttpExceptionHelper.WriteThread( "Unlocking instance {0} {1} {2} Test: \"{3}\" Info:{4}", this.workflowApplication.Id, this.Request.Method, this.Request.RequestUri, this.testName, this.testInfo); Monitor.Exit(this.workflowApplication); } }