/// <summary> /// Invoke an action in the context of a service feature. /// </summary> /// <remarks> /// Assumes that there exists a current <see cref="DreamContext"/> that belongs to a request to another feature of this service. /// </remarks> /// <param name="verb">Http verb.</param> /// <param name="path">Feature path.</param> /// <param name="handler">Action to perform in this context.</param> /// <returns>Exception thrown by handler or null.</returns> public Exception InvokeInServiceContext(string verb, string path, Action handler) { if (handler == null) { throw new ArgumentNullException("handler"); } if (string.IsNullOrEmpty(verb)) { throw new ArgumentNullException("verb"); } if (path == null) { throw new ArgumentNullException("path"); } // create new new environment for execution XUri uri = Self.AtPath(path); DreamContext current = DreamContext.Current; Exception e = TaskEnv.ExecuteNew(delegate { DreamFeatureStage[] stages = new DreamFeatureStage[] { new DreamFeatureStage("InServiceInvokeHandler", InServiceInvokeHandler, DreamAccess.Private) }; // BUGBUGBUG (steveb): when invoking a remote function this way, we're are not running the proloques and epilogues, which leads to errors; // also dream-access attributes are being ignored (i.e. 'public' vs. 'private') DreamMessage message = DreamUtil.AppendHeadersToInternallyForwardedMessage(current.Request, DreamMessage.Ok()); var context = current.CreateContext(verb, uri, new DreamFeature(this, Self, 0, stages, verb, path), message); context.AttachToCurrentTaskEnv(); // pass along host and public-uri information handler(); }, TimerFactory); return(e); }
//--- Constructors --- internal DreamFeatureChain(DreamFeatureStage stage, bool mainStage, DreamContext context, Result <DreamMessage> response, string previousName) { if (context.IsTaskEnvDisposed) { throw new InvalidOperationException("cannot go to next feature state with disposed context"); } this.MainStage = mainStage; _stage = stage; _context = context; _response = response; _previousName = previousName ?? "N/A"; }
//--- Constructors --- /// <summary> /// Create a new feature instance. /// </summary> /// <param name="service">Owning Service.</param> /// <param name="serviceUri">Service Uri.</param> /// <param name="mainStageIndex">Main stage index.</param> /// <param name="stages">Feature stages.</param> /// <param name="verb">Request verb.</param> /// <param name="signature">Feature signature.</param> /// <param name="featureParamAttributes">Feature parameter attributes</param> public DreamFeature(IDreamService service, XUri serviceUri, int mainStageIndex, DreamFeatureStage[] stages, string verb, string signature, IEnumerable<DreamFeatureParamAttribute> featureParamAttributes) { this.Service = service; this.ServiceUri = serviceUri; this.Stages = stages; this.MainStageIndex = mainStageIndex; this.Verb = verb; this.ExceptionTranslators = service.ExceptionTranslators; this.FeatureParamAttributes = featureParamAttributes; ParseFeatureSignature(serviceUri, signature, out this.PathSegments, out _paramNames, out this.OptionalSegments); }
//--- Constructors --- internal DreamFeatureChain(DreamFeatureStage stage, bool mainStage, DreamContext context, Result<DreamMessage> response, string previousName) { if(context.IsTaskEnvDisposed) { throw new InvalidOperationException("cannot go to next feature state with disposed context"); } this.MainStage = mainStage; _stage = stage; _context = context; _response = response; _previousName = previousName ?? "N/A"; }
/// <summary> /// Invoke an action in the context of a service feature. /// </summary> /// <remarks> /// Assumes that there exists a current <see cref="DreamContext"/> that belongs to a request to another feature of this service. /// </remarks> /// <param name="verb">Http verb.</param> /// <param name="path">Feature path.</param> /// <param name="handler">Action to perform in this context.</param> /// <returns>Exception thrown by handler or null.</returns> public Exception InvokeInServiceContext(string verb, string path, Action handler) { if(handler == null) { throw new ArgumentNullException("handler"); } if(string.IsNullOrEmpty(verb)) { throw new ArgumentNullException("verb"); } if(path == null) { throw new ArgumentNullException("path"); } // create new new environment for execution XUri uri = Self.AtPath(path); DreamContext current = DreamContext.Current; Exception e = TaskEnv.ExecuteNew(delegate { DreamFeatureStage[] stages = new DreamFeatureStage[] { new DreamFeatureStage("InServiceInvokeHandler", InServiceInvokeHandler, DreamAccess.Private) }; // BUGBUGBUG (steveb): when invoking a remote function this way, we're are not running the proloques and epilogues, which leads to errors; // also dream-access attributes are being ignored (i.e. 'public' vs. 'private') DreamMessage message = DreamUtil.AppendHeadersToInternallyForwardedMessage(current.Request, DreamMessage.Ok()); var context = current.CreateContext(verb, uri, new DreamFeature(this, Self, 0, stages, verb, path), message); context.AttachToCurrentTaskEnv(); // pass along host and public-uri information handler(); }, TimerFactory); return e; }