Adding WebRequest, WebResponse and Redirect activities.

--HG--
branch : 1.x
extra : source : fe92e546e2636ccd59663b7c33158c0ac66a8dc4
This commit is contained in:
Sipke Schoorstra
2013-05-02 18:51:58 +02:00
parent 87f011ff39
commit dd61361607
6 changed files with 240 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.Localization;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
namespace Orchard.Workflows.Activities {
public class RedirectActivity : Task {
private readonly IWorkContextAccessor _wca;
public RedirectActivity(IWorkContextAccessor wca) {
_wca = wca;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public override bool CanExecute(WorkflowContext workflowContext, ActivityContext activityContext) {
return true;
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
return Enumerable.Empty<LocalizedString>();
}
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext) {
var url = activityContext.GetState<string>("Url");
_wca.GetContext().HttpContext.Response.Redirect(url);
return Enumerable.Empty<LocalizedString>();
}
public override string Name {
get { return "Redirect"; }
}
public override LocalizedString Category {
get { return T("HTTP"); }
}
public override LocalizedString Description {
get { return T("Redirect to the specified URL."); }
}
public override string Form {
get { return "ActionRedirect"; }
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.RegularExpressions;
using Orchard.Localization;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
namespace Orchard.Workflows.Activities {
public class WebRequestActivity : Task {
public WebRequestActivity() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public override bool CanExecute(WorkflowContext workflowContext, ActivityContext activityContext) {
var url = activityContext.GetState<string>("Url");
return !string.IsNullOrWhiteSpace(url);
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
yield return T("Error");
yield return T("Success");
}
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext) {
var url = activityContext.GetState<string>("Url");
var verb = (activityContext.GetState<string>("Verb") ?? "GET").ToUpper();
var headers = activityContext.GetState<string>("Headers");
var formValues = activityContext.GetState<string>("FormValues") ?? "";
using (var httpClient = new HttpClient {BaseAddress = new Uri(url)}) {
HttpResponseMessage response;
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (!String.IsNullOrWhiteSpace(headers)) {
foreach (var header in ParseKeyValueString(headers)) {
httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
switch (verb) {
default:
case "GET":
response = httpClient.GetAsync("").Result;
break;
case "POST":
var format = activityContext.GetState<string>("FormFormat");
switch (format) {
default:
case "KeyValue":
var form = ParseKeyValueString(formValues);
response = httpClient.PostAsync("", new FormUrlEncodedContent(form)).Result;
break;
case "Json":
var json = formValues.Replace("((", "{").Replace("))", "}");
response = httpClient.PostAsync("", new StringContent(json, Encoding.UTF8, "application/json")).Result;
break;
}
break;
}
workflowContext.SetState("WebRequestResponse", response.Content.ReadAsStringAsync().Result);
if (response.IsSuccessStatusCode)
yield return T("Success");
yield return T("Error");
}
}
public override string Name {
get { return "WebRequest"; }
}
public override LocalizedString Category {
get { return T("HTTP"); }
}
public override LocalizedString Description {
get { return T("Performs an HTTP GET or POST request on the specified URL and stores the response as part of the workflow instance."); }
}
public override string Form {
get { return "WebRequestActivity"; }
}
private static IEnumerable<KeyValuePair<string, string>> ParseKeyValueString(string text) {
return Regex.Split(text, "\n\r").Select(x => x.Split(new[] { '=' })).ToDictionary(x => x[0].Trim(), x => x[1].Trim());
}
}
}

View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using Orchard.Localization;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
namespace Orchard.Workflows.Activities {
public class WebResponseActivity : Event {
public WebResponseActivity() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public override bool CanExecute(WorkflowContext workflowContext, ActivityContext activityContext) {
return true;
}
public override bool CanStartWorkflow {
get { return true; }
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
yield return T("Done");
}
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext) {
yield return T("Done");
}
public override string Name {
get { return "WebResponse"; }
}
public override LocalizedString Category {
get { return T("HTTP"); }
}
public override LocalizedString Description {
get { return T("Suspends the workflow until an HTTP request comes in."); }
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Web.Mvc;
using Orchard.Workflows.Services;
namespace Orchard.Workflows.Controllers {
public class WorkflowController : Controller {
private readonly IWorkflowManager _workflowManager;
public WorkflowController(IWorkflowManager workflowManager) {
_workflowManager = workflowManager;
}
// This could be invoked by external applications and services to trigger an event within the workflows.
public ActionResult Callback() {
// Right now, all workflow instances that are at the WebRequest activity node would continue as soon as a request
// to this action comes in, but that should not happen; it should be controlled by activity configuration and evaluations.
_workflowManager.TriggerEvent("WebRequest", null, () => {
var dictionary = new Dictionary<string, object>();
// Let's include query string stuff, so that the WebRequest activity can
// potentially match against certain parameters to decide whether or not it should execute,
// based on its configuration (yet to be defined).
Request.QueryString.CopyTo(dictionary);
return dictionary;
});
// A Redirect may have been set by one of the rule events.
if (!string.IsNullOrEmpty(HttpContext.Response.RedirectLocation))
return new EmptyResult();
return new EmptyResult(); // Or maybe an "OK" string. It shouldn't really matter, just as long as we return HTTP 200 OK.
}
}
}

View File

@@ -55,6 +55,10 @@
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\aspnetwebapi\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -131,7 +135,11 @@
<Compile Include="Activities\ExclusiveBranchActivity.cs" />
<Compile Include="Activities\IsInRoleActivity.cs" />
<Compile Include="Activities\MailActivity.cs" />
<Compile Include="Activities\RedirectActivity.cs" />
<Compile Include="Activities\TimerActivity.cs" />
<Compile Include="Activities\WebRequestActivity.cs" />
<Compile Include="Activities\WebResponseActivity.cs" />
<Compile Include="Controllers\WorkflowController.cs" />
<Compile Include="Forms\TimerForms.cs" />
<Compile Include="Forms\BranchForms.cs" />
<Compile Include="Forms\MailForms.cs" />
@@ -233,6 +241,9 @@
<ItemGroup>
<Content Include="Views\Activity-Publish.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Activity-Redirect.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -0,0 +1,4 @@
<div>
<div>@T("Redirect to {0}", Model.State.Url.Value)</div>
</div>