I would like to know how to make use of SharpArch.WcfClient.Castle.WcfSessionFacility as an alternative to the following verbose-ness.
public ActionResult Index() {
IList<TerritoryDto> territories = null;
// WCF service closing advice taken from http://msdn.microsoft.com/en-us/library/aa355056.aspx
// As alternative to this verbose-ness, use the SharpArch.WcfClient.Castle.WcfSessionFacility
// for automatically closing the WCF service.
try {
territories = territoriesWcfService.GetTerritories();
territoriesWcfService.Close();
}
catch (CommunicationException) {
territoriesWcfService.Abort();
}
catch (TimeoutException) {
territoriesWcfService.Abort();
}
catch (Exception) {
territoriesWcfService.Abort();
throw;
}
return View(territories);
}
The above code has been taken from the TerritoriesController class in SharpArchitecture's NorthWind Sample.
Awaiting
Nabeel
You need to:
Make sure that Windsor knows to call ComponentDestroyed for your client proxies, and that your proxies are registered with "ManageWcfSessions" set to true. Since I'm using it in a web application, I register my client proxies to use a Lifestyle of PerWebRequest:
container
.Register(AllTypes.FromThisAssembly()
.BasedOn(typeof(ClientBase<>))
.WithService.DefaultInterface()
.Configure(c => c
.LifeStyle.Is(LifestyleType.PerWebRequest)
.ExtendedProperties(new { ManageWcfSessions = true }))
);
Add the facility:
container.AddFacility<WcfSessionFacility>(WcfSessionFacility.ManageWcfSessionsKey);
Add the HttpModule to enable the PerWebRequest lifestyle (I can't figure out how to get stackoverflow to format this right - you'll get the idea):
add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor"
Related
I am creating a wcf client on core.
I create a binding.
var binding = new System.ServiceModel.BasicHttpsBinding();
I need to add MessageID, ReplyTo fields to the request for ws-addressing.
How to do it correctly?
I tried to overwrite request - it didn't work.
All examples are mostly on the usual net framework
It seems there is a library microsoft.web.services2, but I do not understand how to use it.
I'm working on the same requirement, I've found the way to modify the header is work with the OperationContextScope and work with OperationContext.Current.OutgoingMessageHeaders and change the properties.
public async Task<getAttorneyResponseStructure> GetAttorneyAsync(GetAttorneyRequestStructure getAttorneyRequestStructure)
{
try
{
using (new OperationContextScope(Client.InnerChannel))
{
//Client Custom Header
getAttorneyRequestStructure.AttorneyHeader = Header;
//Change the properties to ReplyTo/MessageId
OperationContext.Current.OutgoingMessageHeaders.To = new Uri("http://rydwvgsn01.spga.gov.sa/GSBExpress/Legal/MOJAttorneyInquiry/2.0/AttorneyInquiryService.svc");
OperationContext.Current.OutgoingMessageHeaders.Action = "http://tempuri.org/IAttorneyInquiryService/GetAttorney";
return await Client.GetAttorneyAsync(getAttorneyRequestStructure);
}
}
catch (Exception e)
{
throw;
}
}
We have WCF services (web hosted in IIS) separatd by domains. We added some claim based security by adding ClaimsAuthorizationManager and overriding the CheckAccess method. Basicaly, we check if the ClaimsPrincipal have the permission needed to execute the method.
Inside the service method :
public DemandePaeDto ObtenirInfoDemandePAE(int idPreDemande, int numeroSequencePreDemande)
{
if (!ClaimsPrincipal.Current.CheckAccess(Management, "DoSomething"))
return null;
Inside the ClaimsAuthorizationManager :
public class FacadeClaimsAuthorizationManager : ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var user = context.Principal;
var resource = context.Resource.First().Value;
foreach (var action in context.Action)
{
switch (resource)
{
case "Management":
case "Sales":
case "Product":
if (user.HasClaim(OurOwnCustomClaimTypes.Permission, action.Value))
{
return true;
}
break;
//Pour les cas non gérés
default:
return false;
}
}
return false;
}
}
The problem is when we need to test the services functionalities with WCF Storm of other test tool, we don't have the claims because we set the security mode to false. So we would like to add a custom parameter to all calls. That way we'd be able to bypass by returning true in the CheckAccess method. I've think about MessageInpectors, but still am wondering if it's the right approach. I wouldn't like to add the param to the contracts, because I'd have to modify every call in the application.
Do you have a suggestion ?
You will need to use a different ClaimsAuthorizationManager for your tests. Just derive a different version and use that in your testing environment. It could return true on all call for example.
I have three service in my angular service module, and I put
Restangular.setBaseUrl(api_url);
in each of my service with different api_url, and I expect to use different service with different url;
but when I post to one of the service say api_url = a/v1/c/, what I get is post to api_url = b/v1/c;
I think the problem is the setBaseUrl part, for example:
factory.Aservice = function(Restangular){
Restangular.setBaseUrl('/a/v1');
var alist= Restangular.all('c/');
return {
createA:function(){
alist.post(data)
}
}
}
factory.Bservice = function(Restangular){
Restangular.setBaseUrl('/b/v1');
var blist= Restangular.all('d/');
return {
createB:function(){
blist.post(data)
}
}
}
when I call Aservice.createA(),the post url is '/b/v1/c',which is wrong.
any idea why?
You don't seem to understand scoping of a serivce. Angular instantiates services in a lazily-loaded manner. Since both your services operate on the same Restangular, it is normal that whichever service loaded last, would be the one that will override the restangular configuration last:
http://plnkr.co/edit/o974TqeunG9DGQONRNDT?p=preview
I created a Plunkr which illustrates that.
Also created a Plunkr which shows the correct way to do that.
http://plnkr.co/edit/XYEQpLZaRAjxNUImCJMP?p=preview
You can also use separate configurations for each service as explained here: https://github.com/mgonto/restangular#how-to-create-a-restangular-service-with-a-different-configuration-from-the-global-one
app.factory('ServiceA', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
// service has different address from serviceB
RestangularConfigurer.setBaseUrl('http://service-a.example.com/a/v1');
});
});
app.factory('ServiceB', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
// service has different address from serviceA
RestangularConfigurer.setBaseUrl('http://service-b.example.com/b/v1');
});
});
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?
I am running into an issue where RIA Services returns 3 entities from the server (I have verified while debugging on the server process, and have verified via Fiddler that the service is in face returning 3 entities.
I am using MVVM so I am calling Load on the client side using a helper function that I borrowed from a Shawn Wildermuth sample: Here's that code:
// Generic query handling
protected void PerformQuery<T>(DomainContext dc, string name, EntityQuery<T> qry, EventHandler<EntityResultsArgs<T>> evt) where T : Entity
{
dc.Load<T>(qry,(r) =>
{
if (evt != null)
{
try
{
if (r.HasError)
{
evt(this, new EntityResultsArgs<T>(r.Error));
}
else if (r.Entities.Count() > 0)
{
evt(this, new EntityResultsArgs<T>(r.Entities));
}
}
catch (Exception ex)
{
evt(this, new EntityResultsArgs<T>(ex));
}
}
}, null);
}
EntityResultsArgs is a simple class that exposes an exception property (called Error) and a Results property (containing the results if we got any).
On the server we are mapping the result using AutoMapper to our exposed Domain Classes and this particular service call returns IEnumerable.
What am I missing (or what more would help someone figure this out).
Thanks!
Yep, the problem is now confirmed. I was retrieving 3 entities back from the service all with an Id (aka the "[Key]" value) of 0.