Copy T4 template output to new file - file

I'm trying to use T4 templates to make generating migrations for our system slightly easier. The one thing that I can't quite figure out (and this makes me wonder if I'm using T4 templates for the wrong thing) is how to copy the rendered output to a new file. I can manually create a file and copy the contents of the generated file, but that kind of goes against my whole "make things easier" ethos here.
Here's the template I have. Upon rendering, it would ideally get copied to "62-CreateWidgetsTable.cs" in the same directory. The goal is to have a file that I can now edit (I am generating a template, in other words, not generating the complete file.) If I could rename the generated file in VS (and then have the t4 generate a new template that would just sit there until someone came along and used it), that would be good enough.
<## template debug="false" hostspecific="false" language="C#" #>
<## output extension=".cs" #>
<#
var migrationNumber = "62";
var migrationName = "CreateWidgetsTable";
#>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migrator.Framework;
namespace WidgetsIntl.Console.Migrations
{
[Migration(<#= DateTime.UtcNow.ToString("yyyyMMddhhmmss") #>)]
public class _<#= migrationNumber #>_<#= migrationName #> : Migration
{
public override void Up()
{
}
public override void Down()
{
}
}
}

Alright, I figured out a couple ways to do this. The simplest way to do it (which I found only after doing it the way I'm about to show you) is here: t4 append output to existing file. The key information is GenerationEnvironment is a StringBuilder which contains the result of running the template, so you can just write that result to any old file you want!
The other way to do it is to use T4 Toolbox. Go download it!
Then, you can make a template that create a class that extends Template (defined by T4 toolbox) that overrides some default behavior:
<## template language="C#" hostspecific="True" debug="True" #>
<## include file="T4Toolbox.tt" #>
<#
// make an instance of the class we define below, set some variables, and render it
var tpl = new MyT4();
tpl.MyVar = "Do those things you do";
tpl.Render();
#>
<#+
public class MyT4 : Template
{
public MyVar = "some stuff";
public override string TransformText()
{
Output.PreserveExistingFile = true; // tells T4 that you want to manually edit this file afterward (for scaffoling, which was my use case)
Output.File = MyVar + ".cs"; // output will go in "some stuff.cs"
/******************
Template is defined here!
*******************/
#>
public class <#=myVar.Replace(" ", "_") #>
{
public void Method()
{
return "Hi, I am <#= myvar #>";
}
}
<#+
/*************************
now finishing up the TransformText() method
*************************/
return GenerationEnvironment.ToString();
}
}
#>

In some Projects I use allready the FileManager class below. Its a custominated implementation based on this blog post: http://damieng.com/blog/2009/11/06/multiple-outputs-from-t4-made-easy-revisited
<## assembly name="System.Core"
#><## assembly name="System.Data.Linq"
#><## assembly name="EnvDTE"
#><## assembly name="System.Xml"
#><## assembly name="System.Xml.Linq"
#><## import namespace="System"
#><## import namespace="System.CodeDom"
#><## import namespace="System.CodeDom.Compiler"
#><## import namespace="System.Collections.Generic"
#><## import namespace="System.Data.Linq"
#><## import namespace="System.Data.Linq.Mapping"
#><## import namespace="System.IO"
#><## import namespace="System.Linq"
#><## import namespace="System.Reflection"
#><## import namespace="System.Text"
#><## import namespace="System.Xml.Linq"
#><## import namespace="Microsoft.VisualStudio.TextTemplating"
#><#+
// Manager class records the various blocks so it can split them up
protected abstract class FileManager {
protected FileManager(ITextTemplatingEngineHost host, StringBuilder template)
{
this.host = host;
this.template = template;
}
protected abstract void CreateFile(String fileName, String content);
public abstract String GetCustomToolNamespace(String fileName);
public abstract String DefaultProjectNamespace { get; }
public abstract void Process();
public static FileManager Create(ITextTemplatingEngineHost host, StringBuilder template)
{
return new VSManager(host, template);
}
protected class Block
{
public String Name;
public int Start, Length;
}
protected Block currentBlock;
protected List<Block> files = new List<Block>();
protected Block footer = new Block();
protected Block header = new Block();
protected ITextTemplatingEngineHost host;
protected StringBuilder template;
public void StartNewFile(String name)
{
if (name == null)
throw new ArgumentNullException("name");
CurrentBlock = new Block { Name = name };
}
public void StartFooter() {
CurrentBlock = footer;
}
public void StartHeader() {
CurrentBlock = header;
}
public void EndBlock() {
if (CurrentBlock == null)
return;
CurrentBlock.Length = template.Length - CurrentBlock.Start;
if (CurrentBlock != header && CurrentBlock != footer)
files.Add(CurrentBlock);
currentBlock = null;
}
protected bool IsFileContentDifferent(String fileName, String newContent)
{
return !(File.Exists(fileName) && File.ReadAllText(fileName) == newContent);
}
protected Block CurrentBlock
{
get { return currentBlock; }
set {
if (CurrentBlock != null)
EndBlock();
if (value != null)
value.Start = template.Length;
currentBlock = value;
}
}
// VS Manager
private class VSManager: FileManager
{
private EnvDTE.ProjectItem templateProjectItem;
private EnvDTE.DTE dte;
private List<string> generatedFileNames = new List<string>();
public override String DefaultProjectNamespace
{
get
{
return templateProjectItem.ContainingProject.Properties.Item("DefaultNamespace").Value.ToString();
}
}
public override String GetCustomToolNamespace(string fileName)
{
return dte.Solution.FindProjectItem(fileName).Properties.Item("CustomToolNamespace").Value.ToString();
}
public override void Process()
{
EndBlock();
String headerText = template.ToString(header.Start, header.Length);
String footerText = template.ToString(footer.Start, footer.Length);
Directory.SetCurrentDirectory(Path.GetDirectoryName(host.TemplateFile));
files.Reverse();
foreach(Block block in files)
{
String fileName = Path.GetFullPath(block.Name);
String content = headerText + template.ToString(block.Start, block.Length) + footerText;
generatedFileNames.Add(fileName);
CreateFile(fileName, content);
template.Remove(block.Start, block.Length);
}
this.ProjectSync(generatedFileNames);
this.files = new List<Block>();
this.footer = new Block();
this.header = new Block();
this.generatedFileNames = new List<string>();
}
protected override void CreateFile(String fileName, String content)
{
if (IsFileContentDifferent(fileName, content))
{
CheckoutFileIfRequired(fileName);
File.WriteAllText(fileName, content);
}
}
internal VSManager(ITextTemplatingEngineHost host, StringBuilder template) : base(host, template)
{
var hostServiceProvider = host as IServiceProvider;
if (hostServiceProvider == null)
{
throw new ArgumentNullException("Could not obtain IServiceProvider");
}
this.dte = (EnvDTE.DTE) hostServiceProvider.GetService(typeof(EnvDTE.DTE));
if (this.dte == null)
{
throw new ArgumentNullException("Could not obtain DTE from host");
}
}
private void ProjectSync(IEnumerable<string> keepFileNames) {
var projectFiles = new Dictionary<string, EnvDTE.ProjectItem>();
foreach (string keepFileName in keepFileNames)
{
var item = this.dte.Solution.FindProjectItem(keepFileName);
if (item != null)
{
projectFiles.Add(keepFileName, item);
}
}
// Remove unused items from the project
/* foreach(var pair in projectFiles) // NEW
{
if (keepFileNames.Contains(pair.Key))
{
pair.Value.Delete();
}
} */
// Add missing files to the project
foreach(string fileName in keepFileNames)
{
if (!projectFiles.ContainsKey(fileName))
{
EnvDTE.Project targetProj = null;
foreach (EnvDTE.Project proj in this.dte.Solution.Projects)
{
if (string.IsNullOrEmpty(proj.FullName))
{
continue;
}
if (fileName.Contains(Path.GetDirectoryName(proj.FullName) + #"\"))
{
targetProj = proj;
break;
}
}
var targetDir = NavigateTo(targetProj, fileName);
if (targetDir == null)
{
targetProj.ProjectItems.AddFromFile(fileName);
continue;
}
targetDir.ProjectItems.AddFromFile(fileName);
}
}
}
private void CheckoutFileIfRequired(String fileName)
{
var sc = dte.SourceControl;
if (sc != null && sc.IsItemUnderSCC(fileName) && !sc.IsItemCheckedOut(fileName))
{
dte.SourceControl.CheckOutItem(fileName);
}
}
public EnvDTE.ProjectItem NavigateTo(EnvDTE.Project project, string path)
{
if (string.IsNullOrEmpty(project.FullName))
{
return null;
}
var projBase = Path.GetDirectoryName(project.FullName);
var fileBase = Path.GetDirectoryName(path);
var naviBase = fileBase.Replace(projBase + #"\", "");
if (string.IsNullOrEmpty(fileBase.Replace(projBase, "")))
{
return null;
}
var naviPoints = naviBase.Split('\\');
EnvDTE.ProjectItem item = null;
EnvDTE.ProjectItems items = project.ProjectItems;
foreach (var folder in naviPoints)
{
item = items.Item(folder);
items = item.ProjectItems;
}
return item;
}
}
} #>

The easiest way I have found to do this without plugins is to right-click your target project and go to Add -> Existing Item and select your generated file. This makes a copy of the file for you at the root of the project, which you can then move as needed. This allows you to easily transfer generated files to projects besides the one that they were generated in.
I haven't tested what happens when the .tt file is itself in the root of a project, but this definitely works so long as the .tt is in a subfolder (which is probably good practice anyhow).

Related

How to call wpf function via JS when visiting https link

I need to execute a function defined in wpf project, which is called from JS in a https web page.
The demo project of all codes is here: https://github.com/tomxue/WebViewIssueInWpf
JS part:
The web page link is https://cmsdev.lenovo.com.cn/musichtml/leHome/weather/index.html?date=&city=&mark=0&speakerId=&reply=
And it contains below line:
<script src="js/index.js" type="text/javascript" charset="utf-8"></script>
And js/index.js contains below code:
setTitle(dataObject.city + weekDay(dataObject.date) +"天气" )
setTitle() is defined below: uses method of window.external.notify()
function setTitle(_str){
try{
wtjs.setTitle(_str)
}catch(e){
console.log(_str)
window.external.notify(_str);
}
}
The function window.external.notify() will call wpf function via ScriptNotify().
WPF part:
For the WebView inside of the wpf project
this.wv.IsScriptNotifyAllowed = true;
this.wv.ScriptNotify += Wv_ScriptNotify;
And
private void Wv_ScriptNotify(object sender, Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlScriptNotifyEventArgs e)
{
textBlock.Text = e.Value;
}
Problems:
(1)
The problem here is if the web page uses https://, then the above function Wv_ScriptNotify() in wpf will not be fired. But if the web page link uses http://, then the above function Wv_ScriptNotify() in wpf can be fired.
Why and how to solve it?
Update:
2020-3-2 17:25:55, tested just now, https works. I do not know what causes https does not work previously
(2)
JS in the web page uses a object wtjs (defined by ourselves and work well with an UWP project using JSBridge).
And I want to use a similiar method to UWP, using a bridge so that I can add multiple funtions/interfaces for JS to call. The disadvantage of ScriptNotify() is that only one interface is usable.
To achieve it, I make below code, which is commented out now.
wv.RegisterName("wtjs", new myBridge());
And more functions are defined as below
public class myBridge
{
public void SetTitle(string title)
{
Debug.WriteLine("SetTitle is executing...title = {0}", title);
}
public void PlayTTS(string tts)
{
Debug.WriteLine("PlayTTS is executing...tts = {0}", tts);
}
}
While in JS side, corresponding functions will be called.
wtjs.playTTS(tts)
wtjs.setTitle(_str)
But in fact wpf side did not work, while the UWP project using JSBridge works with the web link(so web page and JS script are workable). How to achieve it?
(3)
The above two problems are solved by DK Dhilip's answer already.
But a new problem is found. Please check my GitHub code, update it to latest commit.
https://github.com/tomxue/WebViewIssueInWpf
I put a TextBlock onto WebView and expect to see the text floating on the web content. But in fact, the text is covered by the WebView. Why and how to solve it?
Thanks!
For Problem (1, 2)
HTTPS link worked fine for me, maybe the page is too slow to load?
According to Microsoft (source), only ScriptNotify is supported in WebView:
Can I inject native objects into my WebViewControl content?
No.
Neither the WebBrower (Internet Explorer) ObjectForScripting property
nor the WebView (UWP) AddWebAllowedObject method are supported in
WebViewControl. As a workaround, you can use window.external.notify/
ScriptNotify and JavaScript execution to communicate between the
layers, for example:
https://github.com/rjmurillo/WebView_AddAllowedWebObjectWorkaround
But the above suggested workaround solution seems to work differently to your expectation, so I just implement my own solution to emulate the JSBridge convention you have expected.
My custom solution is not battle-tested, it might break in some edge cases but it seems to work fine in few simple tests.
What's supported:
Multiple bridge objects
JS to C# method call
JS to C# get/set property
C# Usage:
// Add
webView.AddWebAllowedObject("wtjs", new MyBridge(this));
webView.AddWebAllowedObject("myBridge", new MyOtherBridge());
// Remove
webView.RemoveWebAllowedObject("wtjs");
JS Usage:
// Call C# object method (no return value)
wtjs.hello('hello', 'world', 666);
myBridge.saySomething('天猫精灵,叫爸爸!');
// Call C# object method (return value)
wtjs.add(10, 20).then(function (result) { console.log(result); });
// Get C# object property
wtjs.backgroundColor.then(function (color) { console.log(color); });
// Set C# object property
wtjs.niubility = true;
Code
WebViewExtensions.cs
using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
using Microsoft.Toolkit.Wpf.UI.Controls;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Text;
namespace WpfApp3
{
// Source: https://github.com/dotnet/orleans/issues/1269#issuecomment-171233788
public static class JsonHelper
{
private static readonly Type[] _specialNumericTypes = { typeof(ulong), typeof(uint), typeof(ushort), typeof(sbyte) };
public static object ConvertWeaklyTypedValue(object value, Type targetType)
{
if (targetType == null)
throw new ArgumentNullException(nameof(targetType));
if (value == null)
return null;
if (targetType.IsInstanceOfType(value))
return value;
var paramType = Nullable.GetUnderlyingType(targetType) ?? targetType;
if (paramType.IsEnum)
{
if (value is string)
return Enum.Parse(paramType, (string)value);
else
return Enum.ToObject(paramType, value);
}
if (paramType == typeof(Guid))
{
return Guid.Parse((string)value);
}
if (_specialNumericTypes.Contains(paramType))
{
if (value is BigInteger)
return (ulong)(BigInteger)value;
else
return Convert.ChangeType(value, paramType);
}
if (value is long || value is double)
{
return Convert.ChangeType(value, paramType);
}
return value;
}
}
public enum WebViewInteropType
{
Notify = 0,
InvokeMethod = 1,
InvokeMethodWithReturn = 2,
GetProperty = 3,
SetProperty = 4
}
public class WebAllowedObject
{
public WebAllowedObject(WebView webview, string name)
{
WebView = webview;
Name = name;
}
public WebView WebView { get; private set; }
public string Name { get; private set; }
public ConcurrentDictionary<(string, WebViewInteropType), object> FeaturesMap { get; } = new ConcurrentDictionary<(string, WebViewInteropType), object>();
public EventHandler<WebViewControlNavigationCompletedEventArgs> NavigationCompletedHandler { get; set; }
public EventHandler<WebViewControlScriptNotifyEventArgs> ScriptNotifyHandler { get; set; }
}
public static class WebViewExtensions
{
public static bool IsNotification(this WebViewControlScriptNotifyEventArgs e)
{
try
{
var message = JsonConvert.DeserializeObject<dynamic>(e.Value);
if (message["___magic___"] != null)
{
return false;
}
}
catch (Exception) { }
return true;
}
public static void AddWebAllowedObject(this WebView webview, string name, object targetObject)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullException(nameof(name));
if (targetObject == null)
throw new ArgumentNullException(nameof(targetObject));
if (webview.Tag == null)
{
webview.Tag = new ConcurrentDictionary<string, WebAllowedObject>();
}
else if (!(webview.Tag is ConcurrentDictionary<string, WebAllowedObject>))
{
throw new InvalidOperationException("WebView.Tag property is already being used for other purpose.");
}
var webAllowedObjectsMap = webview.Tag as ConcurrentDictionary<string, WebAllowedObject>;
var webAllowedObject = new WebAllowedObject(webview, name);
if (webAllowedObjectsMap.TryAdd(name, webAllowedObject))
{
var objectType = targetObject.GetType();
var methods = objectType.GetMethods();
var properties = objectType.GetProperties();
var jsStringBuilder = new StringBuilder();
jsStringBuilder.Append("(function () {");
jsStringBuilder.Append("window['");
jsStringBuilder.Append(name);
jsStringBuilder.Append("'] = {");
jsStringBuilder.Append("__callback: {},");
jsStringBuilder.Append("__newUuid: function () { return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, function (c) { return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16); }); },");
foreach (var method in methods)
{
if (!method.IsSpecialName)
{
if (method.ReturnType == typeof(void))
{
webAllowedObject.FeaturesMap.TryAdd((method.Name, WebViewInteropType.InvokeMethod), method);
}
else
{
webAllowedObject.FeaturesMap.TryAdd((method.Name, WebViewInteropType.InvokeMethodWithReturn), method);
}
var parameters = method.GetParameters();
var parametersInString = string.Join(",", parameters.Select(x => x.Position).Select(x => "$$" + x.ToString()));
jsStringBuilder.Append(method.Name);
jsStringBuilder.Append(": function (");
jsStringBuilder.Append(parametersInString);
jsStringBuilder.Append(") {");
if (method.ReturnType != typeof(void))
{
jsStringBuilder.Append("var callbackId = window['" + name + "'].__newUuid();");
}
jsStringBuilder.Append("window.external.notify(JSON.stringify({");
jsStringBuilder.Append("source: '");
jsStringBuilder.Append(name);
jsStringBuilder.Append("',");
jsStringBuilder.Append("target: '");
jsStringBuilder.Append(method.Name);
jsStringBuilder.Append("',");
jsStringBuilder.Append("parameters: [");
jsStringBuilder.Append(parametersInString);
jsStringBuilder.Append("]");
if (method.ReturnType != typeof(void))
{
jsStringBuilder.Append(",");
jsStringBuilder.Append("callbackId: callbackId");
}
jsStringBuilder.Append("}), ");
jsStringBuilder.Append((method.ReturnType == typeof(void)) ? (int)WebViewInteropType.InvokeMethod : (int)WebViewInteropType.InvokeMethodWithReturn);
jsStringBuilder.Append(");");
if (method.ReturnType != typeof(void))
{
jsStringBuilder.Append("var promise = new Promise(function (resolve, reject) {");
jsStringBuilder.Append("window['" + name + "'].__callback[callbackId] = { resolve, reject };");
jsStringBuilder.Append("});");
jsStringBuilder.Append("return promise;");
}
jsStringBuilder.Append("},");
}
}
jsStringBuilder.Append("};");
foreach (var property in properties)
{
jsStringBuilder.Append("Object.defineProperty(");
jsStringBuilder.Append("window['");
jsStringBuilder.Append(name);
jsStringBuilder.Append("'], '");
jsStringBuilder.Append(property.Name);
jsStringBuilder.Append("', {");
if (property.CanRead)
{
webAllowedObject.FeaturesMap.TryAdd((property.Name, WebViewInteropType.GetProperty), property);
jsStringBuilder.Append("get: function () {");
jsStringBuilder.Append("var callbackId = window['" + name + "'].__newUuid();");
jsStringBuilder.Append("window.external.notify(JSON.stringify({");
jsStringBuilder.Append("source: '");
jsStringBuilder.Append(name);
jsStringBuilder.Append("',");
jsStringBuilder.Append("target: '");
jsStringBuilder.Append(property.Name);
jsStringBuilder.Append("',");
jsStringBuilder.Append("callbackId: callbackId,");
jsStringBuilder.Append("parameters: []");
jsStringBuilder.Append("}), ");
jsStringBuilder.Append((int)WebViewInteropType.GetProperty);
jsStringBuilder.Append(");");
jsStringBuilder.Append("var promise = new Promise(function (resolve, reject) {");
jsStringBuilder.Append("window['" + name + "'].__callback[callbackId] = { resolve, reject };");
jsStringBuilder.Append("});");
jsStringBuilder.Append("return promise;");
jsStringBuilder.Append("},");
}
if (property.CanWrite)
{
webAllowedObject.FeaturesMap.TryAdd((property.Name, WebViewInteropType.SetProperty), property);
jsStringBuilder.Append("set: function ($$v) {");
jsStringBuilder.Append("window.external.notify(JSON.stringify({");
jsStringBuilder.Append("source: '");
jsStringBuilder.Append(name);
jsStringBuilder.Append("',");
jsStringBuilder.Append("target: '");
jsStringBuilder.Append(property.Name);
jsStringBuilder.Append("',");
jsStringBuilder.Append("parameters: [$$v]");
jsStringBuilder.Append("}), ");
jsStringBuilder.Append((int)WebViewInteropType.SetProperty);
jsStringBuilder.Append(");");
jsStringBuilder.Append("},");
}
jsStringBuilder.Append("});");
}
jsStringBuilder.Append("})();");
var jsString = jsStringBuilder.ToString();
webAllowedObject.NavigationCompletedHandler = (sender, e) =>
{
var isExternalObjectCustomized = webview.InvokeScript("eval", new string[] { "window.external.hasOwnProperty('isCustomized').toString();" }).Equals("true");
if (!isExternalObjectCustomized)
{
webview.InvokeScript("eval", new string[] { #"
(function () {
var originalExternal = window.external;
var customExternal = {
notify: function (message, type = 0) {
if (type === 0) {
originalExternal.notify(message);
} else {
originalExternal.notify(JSON.stringify({
___magic___: true,
type: type,
interop: message
}));
}
},
isCustomized: true
};
window.external = customExternal;
})();" });
}
webview.InvokeScript("eval", new string[] { jsString });
};
webAllowedObject.ScriptNotifyHandler = (sender, e) =>
{
try
{
var message = JsonConvert.DeserializeObject<dynamic>(e.Value);
if (message["___magic___"] != null)
{
var interopType = (WebViewInteropType)message.type;
var interop = JsonConvert.DeserializeObject<dynamic>(message.interop.ToString());
var source = (string)interop.source.ToString();
var target = (string)interop.target.ToString();
var parameters = (object[])interop.parameters.ToObject<object[]>();
if (interopType == WebViewInteropType.InvokeMethod)
{
if (webAllowedObjectsMap.TryGetValue(source, out WebAllowedObject storedWebAllowedObject))
{
if (storedWebAllowedObject.FeaturesMap.TryGetValue((target, interopType), out object methodObject))
{
var method = (MethodInfo)methodObject;
var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();
var convertedParameters = new object[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
convertedParameters[i] = JsonHelper.ConvertWeaklyTypedValue(parameters[i], parameterTypes[i]);
}
method.Invoke(targetObject, convertedParameters);
}
}
}
else if (interopType == WebViewInteropType.InvokeMethodWithReturn)
{
var callbackId = interop.callbackId.ToString();
if (webAllowedObjectsMap.TryGetValue(source, out WebAllowedObject storedWebAllowedObject))
{
if (storedWebAllowedObject.FeaturesMap.TryGetValue((target, interopType), out object methodObject))
{
var method = (MethodInfo)methodObject;
var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();
var convertedParameters = new object[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
convertedParameters[i] = JsonHelper.ConvertWeaklyTypedValue(parameters[i], parameterTypes[i]);
}
var invokeResult = method.Invoke(targetObject, convertedParameters);
webview.InvokeScript("eval", new string[] { string.Format("window['{0}'].__callback['{1}'].resolve({2}); delete window['{0}'].__callback['{1}'];", source, callbackId, JsonConvert.SerializeObject(invokeResult)) });
}
}
}
else if (interopType == WebViewInteropType.GetProperty)
{
var callbackId = interop.callbackId.ToString();
if (webAllowedObjectsMap.TryGetValue(source, out WebAllowedObject storedWebAllowedObject))
{
if (storedWebAllowedObject.FeaturesMap.TryGetValue((target, interopType), out object propertyObject))
{
var property = (PropertyInfo)propertyObject;
var getResult = property.GetValue(targetObject);
webview.InvokeScript("eval", new string[] { string.Format("window['{0}'].__callback['{1}'].resolve({2}); delete window['{0}'].__callback['{1}'];", source, callbackId, JsonConvert.SerializeObject(getResult)) });
}
}
}
else if (interopType == WebViewInteropType.SetProperty)
{
if (webAllowedObjectsMap.TryGetValue(source, out WebAllowedObject storedWebAllowedObject))
{
if (storedWebAllowedObject.FeaturesMap.TryGetValue((target, interopType), out object propertyObject))
{
var property = (PropertyInfo)propertyObject;
property.SetValue(targetObject, JsonHelper.ConvertWeaklyTypedValue(parameters[0], property.PropertyType));
}
}
}
}
}
catch (Exception ex)
{
// Do nothing
}
};
webview.NavigationCompleted += webAllowedObject.NavigationCompletedHandler;
webview.ScriptNotify += webAllowedObject.ScriptNotifyHandler;
}
else
{
throw new InvalidOperationException("Object with the identical name is already exist.");
}
}
public static void RemoveWebAllowedObject(this WebView webview, string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullException(nameof(name));
var allowedWebObjectsMap = webview.Tag as ConcurrentDictionary<string, WebAllowedObject>;
if (allowedWebObjectsMap != null)
{
if (allowedWebObjectsMap.TryRemove(name, out WebAllowedObject webAllowedObject))
{
webview.NavigationCompleted -= webAllowedObject.NavigationCompletedHandler;
webview.ScriptNotify -= webAllowedObject.ScriptNotifyHandler;
webview.InvokeScript("eval", new string[] { "delete window['" + name + "'];" });
}
}
}
}
}
MainWindow.xaml.cs
using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
using System;
using System.Diagnostics;
using System.Windows;
namespace WpfApp3
{
public partial class MainWindow : Window
{
public class MyBridge
{
private readonly MainWindow _window;
public MyBridge(MainWindow window)
{
_window = window;
}
public void setTitle(string title)
{
Debug.WriteLine(string.Format("SetTitle is executing...title = {0}", title));
_window.setTitle(title);
}
public void playTTS(string tts)
{
Debug.WriteLine(string.Format("PlayTTS is executing...tts = {0}", tts));
}
}
public MainWindow()
{
this.InitializeComponent();
this.wv.IsScriptNotifyAllowed = true;
this.wv.ScriptNotify += Wv_ScriptNotify;
this.wv.AddWebAllowedObject("wtjs", new MyBridge(this));
this.Loaded += MainPage_Loaded;
}
private void Wv_ScriptNotify(object sender, WebViewControlScriptNotifyEventArgs e)
{
if (e.IsNotification())
{
Debug.WriteLine(e.Value);
}
}
private void setTitle(string str)
{
textBlock.Text = str;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
this.wv.Source = new Uri("https://cmsdev.lenovo.com.cn/musichtml/leHome/weather/index.html?date=&city=&mark=0&speakerId=&reply=");
}
}
}
Result
Screenshot:
For Problem (3)
According to (1, 2, 3), it is impossible to overlay UI elements on top of WebView/WebBrowser control.
Luckily there is an alternative solution called CefSharp which is based on Chromium web browser and would be good enough for your use case, plus the background animation worked (which doesn't work in original WebView control).
However, there is no perfect solution; WPF design view is unusable with CefSharp (showing Invalid Markup error), but the program will just compile and run. Also, the project can only be built with either x86 or x64 option, AnyCPU will not work.
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
x:Class="WpfApp3.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="grid">
<cefSharp:ChromiumWebBrowser x:Name="wv" HorizontalAlignment="Left" Height="405" Margin="50,0,0,0" VerticalAlignment="Top" Width="725" RenderTransformOrigin="-0.45,-0.75" />
<TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="30,30,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="60" Width="335"/>
</Grid>
</Window>
MainWindow.xaml.cs
using CefSharp;
using System.Diagnostics;
using System.Windows;
namespace WpfApp3
{
public partial class MainWindow : Window
{
public class MyBridge
{
private readonly MainWindow _window;
public MyBridge(MainWindow window)
{
_window = window;
}
public void setTitle(string title)
{
Debug.WriteLine(string.Format("SetTitle is executing...title = {0}", title));
_window.setTitle(title);
}
public void playTTS(string tts)
{
Debug.WriteLine(string.Format("PlayTTS is executing...tts = {0}", tts));
}
}
public MainWindow()
{
this.InitializeComponent();
this.wv.JavascriptObjectRepository.Register("wtjs", new MyBridge(this), true, new BindingOptions() { CamelCaseJavascriptNames = false });
this.wv.FrameLoadStart += Wv_FrameLoadStart;
this.Loaded += MainPage_Loaded;
}
private void Wv_FrameLoadStart(object sender, FrameLoadStartEventArgs e)
{
if (e.Url.StartsWith("https://cmsdev.lenovo.com.cn/musichtml/leHome/weather"))
{
e.Browser.MainFrame.ExecuteJavaScriptAsync("CefSharp.BindObjectAsync('wtjs');");
}
}
private void setTitle(string str)
{
this.Dispatcher.Invoke(() =>
{
textBlock.Text = str;
});
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
this.wv.Address = "https://cmsdev.lenovo.com.cn/musichtml/leHome/weather/index.html?date=&city=&mark=0&speakerId=&reply=";
}
}
}
Screenshot:

Problem loading view with MEF and ExportAttribute

I have a WPF app and I'm trying to use MEF to load viewmodels and view.
I can't successfully load Views.
The code:
public interface IContent
{
void OnNavigatedFrom( );
void OnNavigatedTo( );
}
public interface IContentMetadata
{
string ViewUri { get; }
}
[MetadataAttribute]
public class ExtensionMetadataAttribute : ExportAttribute
{
public string ViewUri { get; private set; }
public ExtensionMetadataAttribute(string uri) : base(typeof(IContentMetadata))
{
this.ViewUri = uri;
}
}
class ViewContentLoader
{
[ImportMany]
public IEnumerable<ExportFactory<IContent, IContentMetadata>> ViewExports
{
get;
set;
}
public object GetView(string uri)
{
// Get the factory for the View.
var viewMapping = ViewExports.FirstOrDefault(o =>
o.Metadata.ViewUri == uri);
if (viewMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. " +
"Could not locate the View.",
uri));
var viewFactory = viewMapping.CreateExport();
var view = viewFactory.Value;
return viewFactory;
}
}
I supposed to use this code like this:
1)Decorate a User control
[Export(typeof(IContent))]
[ExtensionMetadata("CustomPause")]
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
public partial class CustomPause : Page , IContent, IPartImportsSatisfiedNotification
{
public CustomPause()
{
InitializeComponent();
}
}
2) Compose the parts:
var cv = new CompositionContainer(aggregateCatalog);
var mef = new ViewContentLoader();
cv.ComposeParts(mef);
3) Load the view at runtime given a URI, for example:
private void CustomPause_Click(object sender, RoutedEventArgs e)
{
var vc = GlobalContainer.Instance.GetMefContainer() as ViewContentLoader;
MainWindow.MainFrame.Content = vc.GetView ("CustomPause");
}
Problem is this line in the GetView method fails:
var viewMapping = ViewExports.FirstOrDefault(o =>
o.Metadata.ViewUri == uri);
The query fails and so viewMapping is null but composition seems ok and I can see that ViewExports contains an object of type:
{System.ComponentModel.Composition.ExportFactory<EyesGuard.MEF.IContent, EyesGuard.MEF.IContentMetadata>[0]
I don't know where I'm wrong. Do you have a clue?
Gianpaolo
I had forgot this
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
in the MetadataAttribute

How to generate report (Extent Report) in Specflow Project

Currently I am working designing my project in Specflow. I want to implement some reporting to my project. Currently I have created one separate .cs file and kept all my report setting. But these steps are getting unreachable. Can anyone please guide me how i can design my flow and how i can integrate with the feature file?
Please find the below BaseReport.cs file and my Step definition file.
namespace Verivox.CommonLib
{
public class BaseReport
{
public static ExtentReports extent;
public static ExtentTest test;
[BeforeFeature()]
public static void BasicSetUp()
{
//string pth = System.Reflection.Assembly.GetCallingAssembly().CodeBase;
string pth = System.IO.Directory.GetCurrentDirectory();
string actualPath = pth.Substring(0, pth.LastIndexOf("bin"));
string projectPath = new Uri(actualPath).LocalPath;
string reportPath = projectPath + "Reports\\" + FeatureContext.Current.FeatureInfo.Title + ".html";
extent = new ExtentReports(reportPath, true);
extent.LoadConfig(projectPath + "CommonLib\\Extent-config.xml");
}
[BeforeScenario()]
public static void BeforeScenarioSetUp()
{
test = extent.StartTest("Running Scenario -->" + ScenarioContext.Current.ScenarioInfo.Title);
}
[AfterScenario()]
public static void AfterScnario()
{
if (ScenarioContext.Current.TestError != null)
{
var error = ScenarioContext.Current.TestError;
var errormessage = "<pre>" + error.Message + "</pre>";
//Add capture screen shot line here
extent.EndTest(test);
}
}
[AfterFeature()]
public static void EndReport()
{
extent.Flush();
// extent.Close();
}
}
}
Steps
namespace Verivox.Steps
{
[Binding]
class CalculationVerificationSteps
{
[Given(#"I have navigate to Home Page")]
public void GivenIHaveNavigateToHomePage()
{
Browser.Current.Navigate().GoToUrl(ConfigurationManager.AppSettings["seleniumBaseUrl"]);
PropertyCollection.currentPage = new HomePage();
Browser.Current.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
}
[Given(#"Navigate to Mobile Calculator under All Comparison Section")]
public void GivenNavigateToMobileCalculatorUnderAllComparisonSection()
{
PropertyCollection.currentPage.As<HomePage>().MainCompItemClick("Telekommunikation");
PropertyCollection.currentPage.As<HomePage>().SubCompItemClick("Mobilfunk");
PropertyCollection.currentPage.As<HomePage>().CalculatorLinkClick("Mobiles Internet");
}
[Then(#"Mobile Calculator should appear")]
public void ThenMobileCalculatorShouldAppear()
{
Assert.IsTrue(PropertyCollection.currentPage.As<HomePage>().IsMobileInternetCalcExistance());
}
[Then(#"(.*) option and (.*) option is selected by default\.")]
public void ThenMonatsflatrateOptionAndSIMOptionIsSelectedByDefault_(string defaultTarif, string hardware)
{
try
{
Assert.IsTrue(PropertyCollection.currentPage.As<HomePage>().VerifyMobiIntSelectedItem(defaultTarif));
string colorCode = PropertyCollection.currentPage.As<HomePage>().VerifySelectedHardWare();
Assert.AreEqual(0, string.Compare("rgba(253, 138, 2, 1)", colorCode, StringComparison.OrdinalIgnoreCase));
}
catch (Exception)
{
BaseReport.test.Log(LogStatus.Fail, "Default selections are incorrect.");
}
}
You are missing the Binding- attribute on the BaseReport class. Without that, the hooks defined there are not called.

Query CRM data in Silverlight

I am building a silverlight app for CRM 2011 and I was wondering what the best way to retrieve data from the CRM system is.
I have linked in my organisation as a service reference and am able to access that. I have seen a few different ways to retrieve data but they all seem rather complicated. Is there anything like what we can use in plugins such as a fetch XMl query or a simple Service.Retrieve method?
Thanks
If you add a service reference to your project you can use LINQ to query the datasets.
You can download the CSDL from Developer Resources under the customisation area.
private FelineSoftContext context;
private System.String serverUrl;
private DataServiceCollection<SalesOrder> _orders;
public MainPage()
{
InitializeComponent();
serverUrl = (String)GetContext().Invoke("getServerUrl");
//Remove the trailing forward slash returned by CRM Online
//So that it is always consistent with CRM On Premises
if (serverUrl.EndsWith("/"))
serverUrl = serverUrl.Substring(0, serverUrl.Length - 1);
Uri ODataUri = new Uri(serverUrl + "/xrmservices/2011/organizationdata.svc/", UriKind.Absolute);
context = new FelineSoftContext(ODataUri) { IgnoreMissingProperties = true };
var orders = from ord in context.SalesOrderSet
orderby ord.Name
select new SalesOrder
{
Name = ord.Name,
SalesOrderId = ord.SalesOrderId
};
_orders = new DataServiceCollection<SalesOrder>();
_orders.LoadCompleted += _orders_LoadCompleted;
_orders.LoadAsync(orders);
}
void _orders_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
if (e.Error == null)
{
if (_orders.Continuation != null)
{
_orders.LoadNextPartialSetAsync();
}
else
{
OrderLookup.ItemsSource = _orders;
OrderLookup.DisplayMemberPath = "Name";
OrderLookup.SelectedValuePath = "Id";
}
}
}
You will also need to add a method in your class as below:
private static ScriptObject GetContext()
{
ScriptObject xrmProperty = (ScriptObject)HtmlPage.Window.GetProperty("Xrm");
if (null == xrmProperty)
{
//It may be that the global context should be used
try
{
ScriptObject globalContext = (ScriptObject)HtmlPage.Window.Invoke("GetGlobalContext");
return globalContext;
}
catch (System.InvalidOperationException)
{
throw new InvalidOperationException("Property \"Xrm\" is null and the Global Context is not available.");
}
}
ScriptObject pageProperty = (ScriptObject)xrmProperty.GetProperty("Page");
if (null == pageProperty)
{
throw new InvalidOperationException("Property \"Xrm.Page\" is null");
}
ScriptObject contextProperty = (ScriptObject)pageProperty.GetProperty("context");
if (null == contextProperty)
{
throw new InvalidOperationException("Property \"Xrm.Page.context\" is null");
}
return contextProperty;
}
You will need to add an additional class library and put the following code within it. Change the class name to match the Context you exported:
partial class FelineSoftContext
{
#region Methods
partial void OnContextCreated()
{
this.ReadingEntity += this.OnReadingEntity;
this.WritingEntity += this.OnWritingEntity;
}
#endregion
#region Event Handlers
private void OnReadingEntity(object sender, ReadingWritingEntityEventArgs e)
{
ODataEntity entity = e.Entity as ODataEntity;
if (null == entity)
{
return;
}
entity.ClearChangedProperties();
}
private void OnWritingEntity(object sender, ReadingWritingEntityEventArgs e)
{
ODataEntity entity = e.Entity as ODataEntity;
if (null == entity)
{
return;
}
entity.RemoveUnchangedProperties(e.Data);
entity.ClearChangedProperties();
}
#endregion
}
public abstract class ODataEntity
{
private readonly Collection<string> ChangedProperties = new Collection<string>();
public ODataEntity()
{
EventInfo info = this.GetType().GetEvent("PropertyChanged");
if (null != info)
{
PropertyChangedEventHandler method = new PropertyChangedEventHandler(this.OnEntityPropertyChanged);
//Ensure that the method is not attached and reattach it
info.RemoveEventHandler(this, method);
info.AddEventHandler(this, method);
}
}
#region Methods
public void ClearChangedProperties()
{
this.ChangedProperties.Clear();
}
internal void RemoveUnchangedProperties(XElement element)
{
const string AtomNamespace = "http://www.w3.org/2005/Atom";
const string DataServicesNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices";
const string DataServicesMetadataNamespace = DataServicesNamespace + "/metadata";
if (null == element)
{
throw new ArgumentNullException("element");
}
List<XElement> properties = (from c in element.Elements(XName.Get("content", AtomNamespace)
).Elements(XName.Get("properties", DataServicesMetadataNamespace)).Elements()
select c).ToList();
foreach (XElement property in properties)
{
if (!this.ChangedProperties.Contains(property.Name.LocalName))
{
property.Remove();
}
}
}
private void OnEntityPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (!this.ChangedProperties.Contains(e.PropertyName))
{
this.ChangedProperties.Add(e.PropertyName);
}
}
#endregion
}
I am will suggest you to use Silvercrmsoap , it's very easy to use. I have used this in my silverlight projects.

Easy way to dynamically invoke web services (without JDK or proxy classes)

In Python I can consume a web service so easily:
from suds.client import Client
client = Client('http://www.example.org/MyService/wsdl/myservice.wsdl') #create client
result = client.service.myWSMethod("Bubi", 15) #invoke method
print result #print the result returned by the WS method
I'd like to reach such a simple usage with Java.
With Axis or CXF you have to create a web service client, i.e. a package which reproduces all web service methods so that we can invoke them as if they where normal methods. Let's call it proxy classes; usually they are generated by wsdl2java tool.
Useful and user-friendly. But any time I add/modify a web service method and I want to use it in a client program I need to regenerate proxy classes.
So I found CXF DynamicClientFactory, this technique avoids the use of proxy classes:
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
//...
//create client
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://www.example.org/MyService/wsdl/myservice.wsdl");
//invoke method
Object[] res = client.invoke("myWSMethod", "Bubi");
//print the result
System.out.println("Response:\n" + res[0]);
But unfortunately it creates and compiles proxy classes runtime, hence requires JDK on the production machine. I have to avoid this, or at least I can't rely on it.
My question:
Is there another way to dinamically invoke any method of a web service in Java, without having a JDK at runtime and without generating "static" proxy classes? Maybe with a different library? Thanks!
I know this is a really old question but if you are still interested you could use soap-ws github project: https://github.com/reficio/soap-ws
Here you have a sample usage really simple:
Wsdl wsdl = Wsdl.parse("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
SoapBuilder builder = wsdl.binding()
.localPart("CurrencyConvertorSoap")
.find();
SoapOperation operation = builder.operation()
.soapAction("http://www.webserviceX.NET/ConversionRate")
.find();
Request request = builder.buildInputMessage(operation)
SoapClient client = SoapClient.builder()
.endpointUrl("http://www.webservicex.net/CurrencyConvertor.asmx")
.build();
String response = client.post(request);
As you can see it is really simple.
With CXF 3.x this could be possible with StaxDataBinding. Follow below steps to get the basics. Of course, this could be enhanced to your needs.
Create StaxDataBinding something like below. Note below code can be enhanced to your sophistication.
class StaxDataBinding extends AbstractInterceptorProvidingDataBinding {
private XMLStreamDataReader xsrReader;
private XMLStreamDataWriter xswWriter;
public StaxDataBinding() {
super();
this.xsrReader = new XMLStreamDataReader();
this.xswWriter = new XMLStreamDataWriter();
inInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
inFaultInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
inInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
inFaultInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
}
static class RemoveStaxInEndingInterceptor
extends AbstractPhaseInterceptor<Message> {
static final RemoveStaxInEndingInterceptor INSTANCE = new RemoveStaxInEndingInterceptor();
public RemoveStaxInEndingInterceptor() {
super(Phase.PRE_INVOKE);
addBefore(StaxInEndingInterceptor.class.getName());
}
public void handleMessage(Message message) throws Fault {
message.getInterceptorChain().remove(StaxInEndingInterceptor.INSTANCE);
}
}
public void initialize(Service service) {
for (ServiceInfo serviceInfo : service.getServiceInfos()) {
SchemaCollection schemaCollection = serviceInfo.getXmlSchemaCollection();
if (schemaCollection.getXmlSchemas().length > 1) {
// Schemas are already populated.
continue;
}
new ServiceModelVisitor(serviceInfo) {
public void begin(MessagePartInfo part) {
if (part.getTypeQName() != null
|| part.getElementQName() != null) {
return;
}
part.setTypeQName(Constants.XSD_ANYTYPE);
}
}.walk();
}
}
#SuppressWarnings("unchecked")
public <T> DataReader<T> createReader(Class<T> cls) {
if (cls == XMLStreamReader.class) {
return (DataReader<T>) xsrReader;
}
else {
throw new UnsupportedOperationException(
"The type " + cls.getName() + " is not supported.");
}
}
public Class<?>[] getSupportedReaderFormats() {
return new Class[] { XMLStreamReader.class };
}
#SuppressWarnings("unchecked")
public <T> DataWriter<T> createWriter(Class<T> cls) {
if (cls == XMLStreamWriter.class) {
return (DataWriter<T>) xswWriter;
}
else {
throw new UnsupportedOperationException(
"The type " + cls.getName() + " is not supported.");
}
}
public Class<?>[] getSupportedWriterFormats() {
return new Class[] { XMLStreamWriter.class, Node.class };
}
public static class XMLStreamDataReader implements DataReader<XMLStreamReader> {
public Object read(MessagePartInfo part, XMLStreamReader input) {
return read(null, input, part.getTypeClass());
}
public Object read(QName name, XMLStreamReader input, Class<?> type) {
return input;
}
public Object read(XMLStreamReader reader) {
return reader;
}
public void setSchema(Schema s) {
}
public void setAttachments(Collection<Attachment> attachments) {
}
public void setProperty(String prop, Object value) {
}
}
public static class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
private static final Logger LOG = LogUtils
.getL7dLogger(XMLStreamDataWriter.class);
public void write(Object obj, MessagePartInfo part, XMLStreamWriter writer) {
try {
if (!doWrite(obj, writer)) {
// WRITE YOUR LOGIC HOW you WANT TO HANDLE THE INPUT DATA
//BELOW CODE JUST CALLS toString() METHOD
if (part.isElement()) {
QName element = part.getElementQName();
writer.writeStartElement(element.getNamespaceURI(),
element.getLocalPart());
if (obj != null) {
writer.writeCharacters(obj.toString());
}
writer.writeEndElement();
}
}
}
catch (XMLStreamException e) {
throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
}
}
public void write(Object obj, XMLStreamWriter writer) {
try {
if (!doWrite(obj, writer)) {
throw new UnsupportedOperationException("Data types of "
+ obj.getClass() + " are not supported.");
}
}
catch (XMLStreamException e) {
throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
}
}
private boolean doWrite(Object obj, XMLStreamWriter writer)
throws XMLStreamException {
if (obj instanceof XMLStreamReader) {
XMLStreamReader xmlStreamReader = (XMLStreamReader) obj;
StaxUtils.copy(xmlStreamReader, writer);
xmlStreamReader.close();
return true;
}
else if (obj instanceof XMLStreamWriterCallback) {
((XMLStreamWriterCallback) obj).write(writer);
return true;
}
return false;
}
public void setSchema(Schema s) {
}
public void setAttachments(Collection<Attachment> attachments) {
}
public void setProperty(String key, Object value) {
}
}
}
Prepare your input to match the expected input, something like below
private Object[] prepareInput(BindingOperationInfo operInfo, String[] paramNames,
String[] paramValues) {
List<Object> inputs = new ArrayList<Object>();
List<MessagePartInfo> parts = operInfo.getInput().getMessageParts();
if (parts != null && parts.size() > 0) {
for (MessagePartInfo partInfo : parts) {
QName element = partInfo.getElementQName();
String localPart = element.getLocalPart();
// whatever your input data you need to match data value for given element
// below code assumes names are paramNames variable and value in paramValues
for (int i = 0; i < paramNames.length; i++) {
if (paramNames[i].equals(localPart)) {
inputs.add(findParamValue(paramNames, paramValues, localPart));
}
}
}
}
return inputs.toArray();
}
Now set the proper data binding and pass the data
Bus bus = CXFBusFactory.getThreadDefaultBus();
WSDLServiceFactory sf = new WSDLServiceFactory(bus, wsdl);
sf.setAllowElementRefs(false);
Service svc = sf.create();
Client client = new ClientImpl(bus, svc, null,
SimpleEndpointImplFactory.getSingleton());
StaxDataBinding databinding = new StaxDataBinding();
svc.setDataBinding(databinding);
bus.getFeatures().add(new StaxDataBindingFeature());
BindingOperationInfo operInfo = ...//find the operation you need (see below)
Object[] inputs = prepareInput(operInfo, paramNames, paramValues);
client.invoke("operationname", inputs);
If needed you can match operation name something like below
private BindingOperationInfo findBindingOperation(Service service,
String operationName) {
for (ServiceInfo serviceInfo : service.getServiceInfos()) {
Collection<BindingInfo> bindingInfos = serviceInfo.getBindings();
for (BindingInfo bindingInfo : bindingInfos) {
Collection<BindingOperationInfo> operInfos = bindingInfo.getOperations();
for (BindingOperationInfo operInfo : operInfos) {
if (operInfo.getName().getLocalPart().equals(operationName)) {
if (operInfo.isUnwrappedCapable()) {
return operInfo.getUnwrappedOperation();
}
return operInfo;
}
}
}
}
return null;
}

Resources