asp net core soap request ws-addressing - asp.net-core

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;
}
}

Related

ABP: Rebuilding Localization Sources from Custom Provider

I am using ABP v4.9.0 (.NET CORE 2.2) with angular client
I built some custom localization providers. These providers get translation dictionaries from an external API.
I add localization sources on startup with these providers.
var customProvider = new CustomLocalizationProvider(...);
var localizationSource = new DictionaryBasedLocalizationSource("SOURCENAME", customProvider );
config.Localization.Sources.Add(localizationSource );
On startup, the providers InitializeDictionaries() is called and localization dictionaries are built.
So far, so good, working as intended.
Now i'd like to manually Reload these translations on demand, but I can't make this working.
Here is what I tried.
Here I trigger the re-synchronize of the language ressources:
foreach (var localizationSource in _localizationConfiguration.Sources)
{
try
{
localizationSource.Initialize(_localizationConfiguration, _iocResolver);
}
catch (Exception e)
{
Logger.Warn($"Could not get Localization Data for source '{localizationSource.Name}'", e);
}
}
In the custom provider, I first clear the Dictionaries
public class CustomLocalizationProvider : LocalizationDictionaryProviderBase
{
protected int IterationNo = 0;
protected override void InitializeDictionaries()
{
Dictionaries.Clear();
IterationNo += 1;
var deDict = new LocalizationDictionary(new CultureInfo("de-DE"));
deDict["HelloWorld"] = $"Hallo Welt Nummer {IterationNo}";
Dictionaries.Add("de-DE", deDict);
var enDict = new LocalizationDictionary(new CultureInfo("en"));
enDict["HelloWorld"] = $"Hello World number {IterationNo}";
Dictionaries.Add("en", enDict);
}
}
The provider is executed again as expected.
But when I eventually use the localization clientside (angular), I still get the original translations.
What am I missing?
Thanks for the help.
In the meanwhile I had to go for another approach.
I am now using a XmlEmbeddedFileLocalizationDictionaryProvider wrapped by a MultiTenantLocalizationDictionaryProvider.
This way, I am using db-localizations with xml-sources as fallback
Then I manually load the ressources from my API in some appservice. These localizations are then updated in the database by using LanguageTextManager.UpdateStringAsync().

What is the replacement of FormDataCollection in Asp.Net core?

I am trying to use FormDataCOllection in Asp.Net core web api project. As per the documentation it is not there in .net core.
How can I still use it? Or What has replaced it?
You can use the Form property of HttpContext.Request which will return an IFormCollection instance.
FormDataCollection is normally type of the information/class/model sent by forms or grid edit or sumbit links. You can simply use the string as input parameter and then using Json, convert it to the class type you've expected.
Here is an example:
public string NewUser(string values)
{
var message = "";
try
{
var newUser = new User_Detail();
JsonConvert.PopulateObject(values, newUser);
db.User_Detail.Add(newUser);
db.SaveChanges();
message = "User cretaed successfully";
}
catch (Exception ex)
{
message = "An error happened in this method.";
}
return JsonConvert.SerializeObject(message);
}
So, PopulateObject converts your input string (values in this example) to the class you've expected, something similar to FormDataCollection you've needed.
Note: JsonConvert is in Newtonsoft.Json namespace

Passing values in Header

We are consuming an external web service (WCF) in our AX2012 project. We followed the procedure described in the following blog.
We are implementing security by passing the token in the header. However, what i am not sure of is how to do this in AX2012.
the sample code for getting the token is
static void myTestServiceWSDL(Args _args)
{
myServiceWSDL.Proxies.Service.ServiceClient service;
myServiceWSDL.Proxies.Service.LoginData LoginData;
str token;
System.Exception ex;
System.Type type;
try
{
type = CLRInterop::getType('myServiceWSDL.Proxies.Service.ServiceClient');
service = AifUtil::createServiceClient(type);
LoginData = new myServiceWSDL.Proxies.Service.LoginData();
LoginData.set_uName("test");
LoginData.set_pwd("test");
token=service.Login(LoginData);
info(token);
}
catch(Exception::CLRError)
{
ex = CLRInterop::getLastException();
info(CLRInterop::getAnyTypeForObject(ex.ToString()));
}
}
The token comes back fine which confirms the code is working.
Now the question is how to do i set header values for the message.
If it was C# i would have done
using (MemberMasterClient proxy = new MemberMasterClient())
{
using (OperationContextScope scope
= new OperationContextScope(proxy.InnerChannel))
{
// set the message in header
MessageHeader header =
MessageHeader.CreateHeader("SourceApplication",
"urn:spike.WCFHeaderExample:v1",
"WCFClient Application 2");
OperationContext.Current.OutgoingMessageHeaders.Add(header);
Console.WriteLine("Membership Details");
Console.WriteLine("Henry's - {0}", proxy.GetMembership("Henry"));
}
}
}
Could any one let me know how to do the equivalent in X++
One idea which has been on my mind is to write an assembly in C# which can then be called in AX2012. Will give that a go, but the idea is to code this in X++ in AX2012
The only thing you do differently in X++ is creating the proxy using the Aif utility. So basically, your C# example you listed, the only difference would be the proxy = new MemberMasterClient() which goes through AIF. All the other code you can take into X++ as-is (except for the "using"). You just need to have the right assemblies reference in the AOT, and use the full namespace in the code.
Alternatively, as you mentioned, you can just code it all in C# and call that from AX :-)

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?

How to use SharpArch.WcfClient.Castle.WcfSessionFacility

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"