Hosting a self-hosted WF in IIS - wcf

Does anyone know if it's possible to host a self-hosted WorkflowServiceHost application in IIS without turning it into a XAMLX file? If so, how?
Furthermore, does anyone have any good guidelines for deploying XAMLX files in general to IIS 7?
Thanks in advance

You can do the same basic thing by writing your own hosting engine instead of the XAMLX one. You can then load applications via ASP.NET, but have complete control on it's lifespan/lifecycle.
You have to create your own host to load the .XAML workflows into something like a WorkflowApplication and manage the lifespan of that workflow. It looks something like this:
private SqlWorkflowInstanceStore _InstanceStore { get; private set; }
private InstanceHandle _MyInstanceHandle { get; private set; }
_InstanceStore = new SqlWorkflowInstanceStore(DataStore.ConnectionString.Replace("MultipleActiveResultSets=True", "MultipleActiveResultSets=False"));
_InstanceStore.HostLockRenewalPeriod = new TimeSpan(0, 0, 30);
_InstanceStore.InstanceEncodingOption = InstanceEncodingOption.None;
_InstanceStore.InstanceLockedExceptionAction = InstanceLockedExceptionAction.BasicRetry;
_InstanceStore.InstanceCompletionAction = InstanceCompletionAction.DeleteNothing;
_MyInstanceHandle = _InstanceStore.CreateInstanceHandle();
var CreateOwnerCommand = new CreateWorkflowOwnerCommand();
var MyView = _InstanceStore.Execute(_MyInstanceHandle, CreateOwnerCommand, TimeSpan.FromSeconds(30));
_InstanceStore.DefaultInstanceOwner = MyView.InstanceOwner;
WorkflowApplication ThisApplication = null;
if (parameters == null)
ThisApplication = new WorkflowApplication(activity);
else
ThisApplication = new WorkflowApplication(activity, parameters);
ThisApplication.PersistableIdle = e => PersistableIdleAction.Unload;
ThisApplication.InstanceStore = this.InstanceStore;
ThisApplication.Run();
There is a bit more to it then just the above, but it gives the basic concepts of how it would work.
EDIT (3/23/2011)
If anyone wants a copy of the basic code to do this, find a way to contact me.

Related

Can i use System.Runtime.Caching.MemoryCache in cloud web role project?

I would like to use System.Runtime.Caching.MemoryCache in Web role project which contains WCF Service.
Can anybody please let me know that whether we can use System.Runtime.Caching.MemoryCache in Cloud web role project?
If yes please let me know Memory and other constraints.
Yes you can.
You should add the reference to System.Runtime.Caching to the Web Role project, then use something like the code below (it is doing almost nothing and is not a best practice, for sure).
Just tried it with ASP.NET MVC in the Cloud Web Role with the Azure Emulator and it works.
Regarding limits - there are two CacheMemoryLimit and PhysicalMemoryLimit properties you can use for retrieve the needed values. It shows the limit in bytes. I do not know if there are any limits beyond these in terms of in-memory cache in Azure Cloud Services.
private static object _lock = new Object();
private static MemoryCache _cache = new MemoryCache("ThisIsMyCache");
public static object GetItem(string key)
{
lock (_lock)
{
var item = _cache.Get(key);
if (item == null)
{
item = InitiaizeItem(key);
_cache.Set(key, item, new CacheItemPolicy());
}
return item;
}
}
private static object InitiaizeItem(string key)
{
return new { Value = key };
}

What replaces CallContextServiceLocator?

In the beta 8 of ASP.NET 5, I had access to the CallContextServiceLocator. This is no longer available in the RC1.
How can I replace the call to CallContextServiceLocator in the following code below. I am using that code to create test instance of the service.
private static TestServer CreateTestServer(HttpMessageHandler backchannelHttpHandler = null)
{
HostingEnvironment hostingEnvironment = new HostingEnvironment { EnvironmentName = "Testing", };
Microsoft.Extensions.PlatformAbstractions.IApplicationEnvironment appEnv =
CallContextServiceLocator.Locator.ServiceProvider.GetRequiredService<Microsoft.Extensions.PlatformAbstractions.IApplicationEnvironment>();
Startup serviceStartup = new Startup(hostingEnvironment, appEnv, backchannelHttpHandler);
Action<IApplicationBuilder> configureApp = app => serviceStartup.Configure(app, appEnv, new LoggerFactory());
Action<IServiceCollection> configureServices = svc => serviceStartup.ConfigureServices(svc);
WebApplicationBuilder webAppBuilder = new WebApplicationBuilder();
webAppBuilder.Configure(configureApp);
webAppBuilder.ConfigureServices(configureServices);
return new TestServer(webAppBuilder);
}
There's no replacement per se, it's dead gone buried RIP :). You can use platform services to get specific components. Also the hosting API has been revamped to be less sucky so it doesn't require anything to be passed into it by default.
The replacement is PlatformServices.Default from Microsoft.Extensions.PlatformAbstractions

Sitecore Glass mapper GetItem<TypeName>(guid) always return null

I saw a related question:
Sitecore Glass Mapper always null
But unfortunately it does not give a solution for my case.
Here goes a code snippet:
var db = Factory.GetDatabase("master");
var context = new SitecoreContext();
// the ID of Needed item
var g = new Guid("{F21C04FE-8826-41AB-9F3C-F7BDF5B35C76}");
// just to test if it's possible to fetch item using db.GetItem
var i = db.GetItem(new ID(g), Language.Current, Sitecore.Data.Version.Latest);
// Grab item
var t = context.GetItem<Article>(g);
In the code above:
i is not null
t is null
Article is the simple class like:
[SitecoreType(TemplateId = "{4C4EC1DA-EB77-4001-A7F9-E4C2F61A9BE9}")]
public class Article
{
[SitecoreField(FieldName = "Title")]
public string Title { get; set; }
}
There are only one language installed in Sitecore - en, it has been specified in the web.config in the items as well.
Also I have added GlassMapperSc.Start(); to Application_Start in the Global.asax.cs and added my assembly to the list of included assemblies via var attributes = new AttributeConfigurationLoader(new[] { "Assembly.Name" }); and I succeeded to find my class in the SitecoreContext mappings.
It does not looks like a language issue, as stated in the link provided in the very beginning. And I'm struggling with it already for a pretty long time, but no luck...
Thank You!
I just noticed that you are using master db for the Sitecore DB and SitecoreContext for Glass.
The SitecoreContext class will use the database that is defined by the Sitecore.Context.Database property at runtime. This probably means that it is using the web database.
Can you check that you have published the item to the web database or instead using:
var context = new SitecoreService("master");

wcf service stop responding i think it because the application is not closing connactions to wcf

this is not my wcf service but i would like to fix it
i need second opinion
here is the code of opening the service from silverlight
i can not put all the code because the project is very big
i just do not see in all the project a m_MdxService.close()
and i think problem off randomly the wcf stop responding
and the only thing fixing it is recycling appication pool
is because the silverlight is not closing the wcf object .
the wcf service is running on it own application pool . the server is 64 bit
public abstract class CubeControl : Control, IFilter
{
protected MdxClient m_MdxService;
protected GeneralClient m_GeneralService;
protected PortalClient m_PortalService;
protected ListsSoapClient m_PortalListsService;
public GraphControl(string cubeName, SharedContract.Filters filter)
: base(cubeName)
{
AttachEvents();
Init(filter);
}
public override void UpdateGraph()
{
flipable.Visibility = Visibility.Collapsed;
progressStackPanel.Visibility = Visibility.Visible;
noDataStackPanel.Visibility = Visibility.Collapsed;
DataPointEventArgs dpe;
switch (m_DrillLevel)
{
case 0:
m_MdxService.GetGraphDataAsync(SharedContract.Enums.Query.NumberOfEmployees, Filter, null, null);
break;
case 1:
dpe = m_DrillParam as DataPointEventArgs;
m_MdxService.GetGraphDataAsync(SharedContract.Enums.Query.NumberOfEmployeesYears, Filter, dpe.Key, null);
break;
case 2:
dpe = m_DrillParam as DataPointEventArgs;
string temp = selectedYear + "," + dpe.Key.ToString();
m_MdxService.GetGraphDataAsync(SharedContract.Enums.Query.NumberOfEmployeesMonth, Filter, temp, null);
break;
}
}
void InitServices()
{
m_MdxService = new MdxClient();
m_MdxService.InnerChannel.OperationTimeout = new TimeSpan(0, 4, 0);
m_GeneralService = new GeneralClient();
m_GeneralService.InnerChannel.OperationTimeout = new TimeSpan(0, 4, 0);
m_PortalService = new PortalClient();
m_PortalService.InnerChannel.OperationTimeout = new TimeSpan(0, 4, 0);
m_PortalListsService = new ListsSoapClient();
m_PortalListsService.InnerChannel.OperationTimeout = new TimeSpan(0, 4, 0);
}
void AttachEvents()
{
m_MdxService.GetGraphDataCompleted += new EventHandler<GetGraphDataCompletedEventArgs>(m_MdxService_GetGraphDataCompleted);
}
void m_MdxService_GetGraphDataCompleted(object sender, GetGraphDataCompletedEventArgs e)
{
GetGraphDataCompleted(sender, e);
GetDataCompleted(this);
}
}
Instead of creating the client withing the control why not have a central access and creating point for the service proxy withing your silverlight client.
Eg. On the application class of your silverlight app add a member MdxService of type "proxy". Then at application startup time configure the binding and endpoint and create the instance.
Then within your control access it using App.Current.MdxService.GetGraphDataAsync also register for the completed event with App.Current.MdxService..GetGraphDataCompleted.
That way you have one instance of your service client.
I do however think that your issue runs deeper and you need to find the root cause.If the application pool needs recycling there definitely some other cause in my mind. Have a look at the size of your workingset on the server hosting the service. It might be that api has causing memory issues. If its around 900MB and appPool is running in 32bit mode you have a problem on server if 64bit mode it will be able to handle much more tho.
maybe think about running that service separately. In its own application pool and compile and deploy it separately.
Hope helps
Cheers

Providing workflow extensions to a workflow service - WF 4.0

Greetings one and all!
I'm new to WF 4.0 and WWF in general so forgive me if this seems like a newbie type of question, but believe me I've scoured the depths of the Internet for a solution to this problem, but to no avail.
I have created a sample WF application with a custom CodeActivity that requires an extension be provided, as per below:
public sealed class PreparePizza : CodeActivity
{
public InArgument<Order> Order { get; set; }
protected override void CacheMetadata(CodeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
if (this.Order == null)
metadata.AddValidationError("You must supply an Order.");
metadata.RequireExtension<IPreparePizzaExtension>();
}
// If your activity returns a value, derive from CodeActivity<TResult>
// and return the value from the Execute method.
protected override void Execute(CodeActivityContext context)
{
// Obtain the runtime value of the Text input argument
Order order = context.GetValue(this.Order);
var extension = context.GetExtension<IPreparePizzaExtension>();
extension.Prepare(order);
}
}
public interface IPreparePizzaExtension
{
void Prepare(Order order);
}
I then slot this activity into a workflow service and attempt to consume via my web app by adding a service reference. However, when I add the reference I get:
System.Activities.ValidationException: An extension of type 'PizzaMan.ActivityLibrary.IPreparePizzaExtension' must be configured in order to run this workflow.
Fair enough - of course my activity requires that I pass it an implementation of IPreparePizzaExtension - after all, I've told it to!
So my question is, how on earth do I pass this to the service? I can manage this easily enough in a console app scenario, using the WorkflowInvoker, but I cannot see any obvious way to do this via the service approach. I would assume that obviously a programmatic approach to adding the reference is what's needed, but again I'm at a loss as to precisely how to go about this.
Any help would be greatly appreciated.
Best regards
Ian
The WorkflowServiceHost has a WorkflowExtensions property where you can add the workflow extenstion. There are several ways you can do that. If you are self hosting this is easy as you create the WorkflowServiceHost. If you are usign IIS you need to create a ServiceHostFactory to configure you WorkflowServiceHost. Finally there is an option to add the workflow extension in the CacheMetadata of your activity using the metadata.AddDefaultExtensionProvider() function.
Solved it as follows, self-hosting style:
static void Main(string[] args)
{
Workflow1 workflow = new Workflow1();
// Provide some default values; note: these will be overriden once method on the service is called.
workflow.productID = -1;
Uri address = new Uri("http://localhost:1234/WorkflowService1");
WorkflowServiceHost host = new WorkflowServiceHost(workflow, address);
// Behaviours
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
// Persistence
var connStr = #"";
var behavior = new SqlWorkflowInstanceStoreBehavior(connStr);
behavior.InstanceCompletionAction = InstanceCompletionAction.DeleteNothing;
behavior.InstanceLockedExceptionAction = InstanceLockedExceptionAction.AggressiveRetry;
behavior.InstanceEncodingOption = InstanceEncodingOption.None;
host.Description.Behaviors.Add(behavior);
// Add extension implementations
if (!TEST_MODE)
{
host.WorkflowExtensions.Add(new MyExtension());
}
else
{
host.WorkflowExtensions.Add(new MyExtensionTest());
}
host.Faulted += new EventHandler(host_Faulted);
host.Open();
foreach (System.ServiceModel.Description.ServiceEndpoint endpoint in host.Description.Endpoints)
{
Console.WriteLine(endpoint.Address);
}
Console.WriteLine("Listening...");
Console.ReadLine();
host.Close();
}
My toolkit has configuration support for this. See http://neovolve.codeplex.com/wikipage?title=Neovolve.Toolkit.Workflow.dll%20-%201.1
There is also this method of doing things:
http://wf.codeplex.com/wikipage?title=How%20do%20I%20add%20an%20extension%20to%20a%20WCF%20Workflow%20Service?