Registration Free COM, Threading Models, MT.exe and *.RGS scripts - com

I have a registration free C++ COM component whose manifest I am generating with mt.exe using VS2010. Everything works except I cannot specify which threading model my classes use. I created a small repro project, whose generated manifest file (RGS.dll.embed.manifest) is as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<file name="RGS.dll" hashalg="SHA1">
<comClass clsid="{4EB506E0-0D9C-4281-9B61-F027376E21C3}" tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}"></comClass>
<typelib tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib>
</file>
<comInterfaceExternalProxyStub name="IRgsObject1" iid="{4620CAB8-3E56-42EC-818E-8A55DF9267B7}" tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub>
</assembly>
The part I have a problem with is the comClass node
<comClass clsid="{4EB506E0-0D9C-4281-9B61-F027376E21C3}"
tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}"></comClass>
should have a threadingModel attribute, as in "Sxs and Registration Free COM activation" example at the following page:
http://blogs.msdn.com/b/junfeng/archive/2006/04/20/579748.aspx
I know the threading model isn't specified in the *.tlb, but from Sen Harada's comment on the MSDN docs for mt.exe, you should be able to specify one in a Registration Script file (*.rgs)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa375649(v=vs.85).aspx
So I have the *.rgs file that the ATL wizard created
HKCR
{
NoRemove CLSID
{
ForceRemove {4EB506E0-0D9C-4281-9B61-F027376E21C3} = s 'RgsObject1 Class'
{
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{6B48D06F-A84C-4B72-A70F-F1B091789E67}'
Version = s '1.0'
}
}
}
So I give the *.rgs file to mt.exe
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /out:"Debug\RGS.dll.embed.manifest" /tlb:"Debug\RGS.tlb" /rgs:"RgsObject1.rgs" /dll:"RGS.dll" /manifest Debug\RGS.dll.intermediate.manifest
And see from the build log that it has successfully parsed the *.rgs file
Valid GUID!!! {4EB506E0-0D9C-4281-9B61-F027376E21C3}
Adding entry ClsidTable[{4EB506E0-0D9C-4281-9B61-F027376E21C3}] = RgsObject1 Class
CManGenLib.ParseFileContents::Appending class {00000000-0000-0000-0000-000000000000}
Processed .RGS file successfully
Found type library in file , guid {6B48D06F-A84C-4B72-A70F-F1B091789E67} (contains 2 types)
CManGenLib.ProcessTlb::Appending class {6B48D06F-A84C-4B72-A70F-F1B091789E67}
Found interface {4620CAB8-3E56-42EC-818E-8A55DF9267B7} 'IRgsObject1'
Processed .TLB file successfully
Looking for pstub {4620CAB8-3E56-42EC-818E-8A55DF9267B7} (IRgsObject1)
(specifically the "Valid GUID!!!" line is gone without the rgs: parameter to mt.exe)
YET my RGS.dll.embed.manifest doesn't have the threadingModel attribute.
This person is the only one online I can find talking about the problem, http://social.msdn.microsoft.com/Forums/en-US/vcmfcatl/thread/dbab28cd-023f-45b1-be62-7dc71e8d3d9f , and he never found a solution and edited the manifest after it was generated. Does anyone know how the mt.exe tool uses the RGS file to create the manifest, and what I need to do to get a threadingModel out the other end?

Interesting... it looks like some vestigial ProgId stuff needs to be there for mt.exe to be happy. Specifically, the following *.rgs
HKCR
{
AtlObjectProgId.1 = s 'AtlObject Class'
{
CLSID = s '{2371607D-284A-4D7C-A6DD-20C15373F43F}'
}
NoRemove CLSID
{
ForceRemove {2371607D-284A-4D7C-A6DD-20C15373F43F} = s 'AtlObject Class'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Free'
}
}
}
}
produces the following *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="ATLProject2.dll" hashalg="SHA1"><comClass clsid="{2371607D-284A-4D7C-A6DD-20C15373F43F}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" threadingModel="Free"></comClass><typelib tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><comInterfaceExternalProxyStub name="IAtlObject" iid="{81A8B3DA-2AFE-4C25-B0ED-CDD777FB01A4}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>
whereas the following *.rgs
HKCR
{
NoRemove CLSID
{
ForceRemove {2371607D-284A-4D7C-A6DD-20C15373F43F} = s 'AtlObject Class'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Free'
}
}
}
}
produces the following *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="ATLProject2.dll" hashalg="SHA1"><comClass clsid="{2371607D-284A-4D7C-A6DD-20C15373F43F}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}"></comClass><typelib tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><comInterfaceExternalProxyStub name="IAtlObject" iid="{81A8B3DA-2AFE-4C25-B0ED-CDD777FB01A4}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>
Edit: It appears that this works, but it only works for the first class in the *.rgs file. For example, the following *.rgs
HKCR
{
AtlObj1ProgId.1 = s 'AtlObj1 Class'
{
CLSID = s '{D15A646A-4F2F-42C2-BA8B-780AABCFB133}'
}
AtlObj1ProgId = s 'AtlObj1 Class'
{
CurVer = s 'AtlObj1ProgId.1'
}
NoRemove CLSID
{
ForceRemove {D15A646A-4F2F-42C2-BA8B-780AABCFB133} = s 'AtlObj1 Class'
{
ProgID = s 'AtlObj1ProgId.1'
VersionIndependentProgID = s 'AtlObj1ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
AltObj2ProgId.1 = s 'AtlObj2 Class'
{
CLSID = s '{C208B430-8E12-4C65-AA5A-899F6AB13C4B}'
}
AltObj2ProgId = s 'AtlObj2 Class'
{
CurVer = s 'AltObj2ProgId.1'
}
NoRemove CLSID
{
ForceRemove {C208B430-8E12-4C65-AA5A-899F6AB13C4B} = s 'AtlObj2 Class'
{
ProgID = s 'AltObj2ProgId.1'
VersionIndependentProgID = s 'AltObj2ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
}
Produces the following *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="RgsClass2.dll" hashalg="SHA1"><comClass clsid="{D15A646A-4F2F-42C2-BA8B-780AABCFB133}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" threadingModel="Neutral" progid="AltObj2ProgId"><progid>AtlObj1ProgId.1</progid><progid>AltObj2ProgId.1</progid></comClass><comClass clsid="{C208B430-8E12-4C65-AA5A-899F6AB13C4B}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}"></comClass><typelib tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo><comInterfaceExternalProxyStub name="IAtlObj1" iid="{FF2A4D47-DADA-451E-8125-610643B00FBC}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub><comInterfaceExternalProxyStub name="IAtlObj2" iid="{F9226919-2AB7-4DBE-9F79-092839480351}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>
Observe that only the first CoClass has a threadingModel (or a ProgId for that matter).
Edit: Success! The following *.rgs
HKCR
{
AtlObj1ProgId.1 = s 'AtlObj1 Class'
{
CLSID = s '{D15A646A-4F2F-42C2-BA8B-780AABCFB133}'
}
NoRemove CLSID
{
ForceRemove {D15A646A-4F2F-42C2-BA8B-780AABCFB133} = s 'AtlObj1 Class'
{
ProgID = s 'AtlObj1ProgId.1'
VersionIndependentProgID = s 'AtlObj1ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
}
HKCR
{
AltObj2ProgId.1 = s 'AtlObj2 Class'
{
CLSID = s '{C208B430-8E12-4C65-AA5A-899F6AB13C4B}'
}
NoRemove CLSID
{
ForceRemove {C208B430-8E12-4C65-AA5A-899F6AB13C4B} = s 'AtlObj2 Class'
{
ProgID = s 'AltObj2ProgId.1'
VersionIndependentProgID = s 'AltObj2ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
}
produces the following *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="RgsClass2.dll" hashalg="SHA1"><comClass clsid="{D15A646A-4F2F-42C2-BA8B-780AABCFB133}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" threadingModel="Neutral" progid="AtlObj1ProgId"><progid>AtlObj1ProgId.1</progid></comClass><comClass clsid="{C208B430-8E12-4C65-AA5A-899F6AB13C4B}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" threadingModel="Neutral" progid="AltObj2ProgId"><progid>AltObj2ProgId.1</progid></comClass><typelib tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo><comInterfaceExternalProxyStub name="IAtlObj1" iid="{FF2A4D47-DADA-451E-8125-610643B00FBC}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub><comInterfaceExternalProxyStub name="IAtlObj2" iid="{F9226919-2AB7-4DBE-9F79-092839480351}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>

Related

Jackson UnrecognizedProperyException when parsing XML

I am trying to parse an XML where I generate the DTOs using maven-jaxb2-plugin from xsd file. But I get this exception and don't know why, everything seems alright.
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Publish_Date" (class com.compnay.package.SdnList$PublshInformation), not marked as ignorable (2 known properties: "publishDate", "recordCount"])
at [Source: (PushbackInputStream); line: 4, column: 44] (through reference chain: com.compnay.package.SdnList["publshInformation"]->com.compnay.package.domain.SdnList$PublshInformation["Publish_Date"])
Jaxb execution for the relevant xsd
<execution>
<id>tds</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemas>
<schema>
<url>xsd url</url>
</schema>
</schemas>
<generatePackage>com.company.domain</generatePackage>
<generateDirectory>${project.basedir}/domain/src/main/java</generateDirectory>
<episode>false</episode>
</configuration>
</execution>
Part of the XML file where I get the error.
<publshInformation>
<Publish_Date>08/06/2021</Publish_Date>
<Record_Count>9030</Record_Count>
</publshInformation>
Rest template Configuration
JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
final XmlMapper xmlMapper = new XmlMapper(module);
xmlMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Works when this is on
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(xmlMapper);
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML));
return new RestTemplateBuilder()
.setReadTimeout(Duration.ofMillis(readTimeout))
.setConnectTimeout(Duration.ofMillis(connectTimeout))
.messageConverters(converter)
.build();
Part of a Generated DTO
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"publshInformation",
"sdnEntry"
})
#XmlRootElement(name = "sdnList")
public class SdnList {
#XmlElement(required = true)
protected SdnList.PublshInformation publshInformation;
#XmlElement(required = true)
protected List<SdnList.SdnEntry> sdnEntry;
........
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Publish_Date" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="Record_Count" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"publishDate",
"recordCount"
})
public static class PublshInformation {
#XmlElement(name = "Publish_Date")
protected String publishDate;
#XmlElement(name = "Record_Count")
protected Integer recordCount;
........
}
}
I can make it work with using xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) but I don't want to lose other data. Can anyone help me figure it out why I get unrecognizedPropertyException? I will appreciate any pointers.
I guess you are doing something before the derealization which is making your input stream empty due to which you are getting this error. I used the provided XML and seems to work fine for me:
XML:
<publshInformation>
<Publish_Date>08/06/2021</Publish_Date>
<Record_Count>9030</Record_Count>
</publshInformation>
PublshInformation.class:
#XmlRootElement(name = "publshInformation")
#Data
#XmlAccessorType(XmlAccessType.FIELD)
public class PublshInformation {
#XmlElement(name = "Publish_Date")
private String Publish_Date;
#XmlElement(name = "Record_Count")
private Integer recordCount;
}
PublishMain.class:
public class PublishMain {
public static void main(String[] args) throws JAXBException, XMLStreamException, IOException {
final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("publish.xml");
final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
/* final Unmarshaller unmarshaller = JAXBContext.newInstance(PublshInformation.class).createUnmarshaller();
final PublshInformation publshInformation = unmarshaller.unmarshal(xmlStreamReader, PublshInformation.class).getValue();
System.out.println(publshInformation.toString());
Marshaller marshaller = JAXBContext.newInstance(PublshInformation.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(publshInformation, System.out);*/
System.out.println(inputStream);
final XmlMapper xmlMapper = new XmlMapper();
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
PublshInformation jacksonPublish = xmlMapper.readValue(xmlStreamReader, PublshInformation.class);
System.out.println(jacksonPublish);
xmlMapper.writerWithDefaultPrettyPrinter().writeValue(System.out, jacksonPublish);
}
}
This would produce the result:
java.io.BufferedInputStream#73a28541
PublshInformation(Publish_Date=null, recordCount=null)
<PublshInformation>
<recordCount/>
<publish_Date/>
</PublshInformation>
The above code works even by using the pure JAXB. If you uncomment then it will do it using the JAXB. I used the latest jackson-dataformat-xml 2.12.4
Make your fields private.
Use the latest version of the Jackson
Ensure your input is not being used before which may become empty.
This should work I believe.

Magento 2 : Add custom notification in admin

I see some module has a custom notification, my question is how to add it in my module
hope someone helps me. Thank.
To get your module's custom notification class to run, you need to create the file VendorName/ModuleName/etc/adminhtml/di.xml with the following code:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Notification\MessageList">
<arguments>
<argument name="messages" xsi:type="array">
<item name="yourClassName" xsi:type="string">VendorName\ModuleName\Model\System\Message\YourClassName</item>
</argument>
</arguments>
</type>
</config>
Then you have to create the VendorName\ModuleName\Model\System\Message\YourClassName.php class file with the following code:
<?php
namespace VendorName\ModuleName\Model\System\Message;
class YourClassName implements \Magento\Framework\Notification\MessageInterface
{
public function getIdentity()
{
// Retrieve unique message identity
return 'identity';
}
public function isDisplayed()
{
// Return true to show your message, false to hide it
return true;
}
public function getText()
{
// Retrieve message text
return 'Notification message text goes here';
}
public function getSeverity()
{
// Possible values: SEVERITY_CRITICAL, SEVERITY_MAJOR, SEVERITY_MINOR, SEVERITY_NOTICE
return self::SEVERITY_MAJOR;
}
}

xamarin forms get pdf path

I've successfully read a pdf from the project and displayed in a WebView. What I want to do is to get the pdf file path from my project and check if it exists to display it, and if not, to give it another URI to open with. Anyone knows how I can get the path of the pdf and it works for both Android and iOS.
Here is my C# code:
string internalstorageurl = string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode("Conctionprofile.pdf"));
public pdfviewer ()
{
InitializeComponent ();
PDFReading();
}
private void PDFReading()
{
pdfwebview.Uri = internalstorageurl;
}
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AppXamarin.CustomRenders"
x:Class="AppXamarin.Pages.pdfviewer"
Padding="0,20,0,0">
<ContentPage.Content>
<local:CustomWebView x:Name="pdfwebview" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</ContentPage.Content>
</ContentPage>
I'm checking if the file exist in my project with this code:
[assembly: Dependency(typeof(GetPdfFilePath_Android))]
namespace AppXamarin.Droid.CustomRender
{
public class GetPdfFilePath_Android : Java.Lang.Object, IGetPdfFilePath
{
public string filePath(string fileName)
{
string internalstorageurl = string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode(fileName));
if (File.Exists(internalstorageurl))
return internalstorageurl;
else
return "not found";
}
}
}
The if statement is always false
You can use dependencyService to get pdf file path from both iOS and Android app.
The interface:
public interface IGetPdfFilePath
{
string filePath(string fileName);
}
Get the file path in Xamarin.forms:
string pdfPath = DependencyService.Get<IGetPdfFilePath>().filePath("myPdf.pdf");
Console.WriteLine(pdfPath);
In iOS, the path is depending on where you store the file:
[assembly: Dependency (typeof (GetPdfFilePath_iOS))]
namespace UsingDependencyService.iOS
{
public class GetPdfFilePath_iOS : IGetPdfFilePath
{
public GetPdfFilePath_iOS ()
{
}
public string filePath(string fileName)
{
// 1. if your store your pdf in DocumentDirectory
//string directories = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.All)[0];
//string pathBundle = directories + "/" + fileName;
////bool fileExists = NSFileManager.DefaultManager.FileExists(pathBundle);
//return pathBundle;
//2.pdf file in your project
string pathBundle = Path.Combine(NSBundle.MainBundle.ResourcePath, fileName);
return pathBundle;
}
}
}
In Android:
[assembly: Dependency(typeof(GetPdfFilePath_Android))]
namespace UsingDependencyService.Android
{
public class GetPdfFilePath_Android : Java.Lang.Object, IGetPdfFilePath
{
public string filePath(string fileName)
{
string internalstorageurl = string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode(fileName));
return internalstorageurl;
}
}
}
Update:
Add this line: [assembly: Dependency(typeof(GetPdfFilePath_Android))] to your Android class. GetPdfFilePath_Android here is your class name.
Another way is to create a custom renderer of your webview, you can have a look at this project.
Update to check file:, I add this method in the Android to check if the file exist inside Assets/Content.
public bool fileExist (string fileName) {
AssetManager assets = MainActivity.Instance.Assets;
string[] names = assets.List("Content");
for (int i = 0; i < names.Length; i++)
{
if (names[i] == fileName)
{
return true;
}
}
return false;
}
Note: You have to change the build action of pdf file to AndroidAsset if you can't find the file inside Assets.

Springfox API docu with xml response- Workaround for #XmlAttribute

I have some issues setting up Springfox for usage in Swagger UI.
I got it working in general, but the XML examples which are created are partly wrong because some xml annoations are not considered by springfox.
I have these models:
#XmlRootElement(name = "ApplicatorUnits")
#XmlAccessorType(XmlAccessType.FIELD)
public class EHDTOApplicatorUnits
{
#XmlElement(name = "UnitGroup")
private List<EHDTOUnitGroup> ehdtoUnitGroups;
public List<EHDTOUnitGroup> getEhdtoUnitGroups()
{
return ehdtoUnitGroups;
}
public void setEhdtoUnitGroups(List<EHDTOUnitGroup> ehdtoUnitGroups)
{
this.ehdtoUnitGroups = ehdtoUnitGroups;
}
}
#XmlRootElement(name = "UnitGroup")
#XmlAccessorType(XmlAccessType.FIELD)
public class EHDTOUnitGroup
{
#XmlAttribute(name = "name")
private String name;
#XmlElement(name = "unit")
private List<EHDTOUnit> ehdtoUnits;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public List<EHDTOUnit> getEhdtoUnits()
{
return ehdtoUnits;
}
public void setEhdtoUnits(List<EHDTOUnit> ehdtoUnits)
{
this.ehdtoUnits = ehdtoUnits;
}
}
You see some usages of #XmlAttribute, #XmlRootElement and #XmlElement.
After adding jackson jaxb annotation introspectors (I tried different ways) the XML was partly correct, as the #XmlAttribute annotations have been considered after this step:
JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
jaxbAnnotationModule.setPriority(Priority.PRIMARY);
mapper.registerModule(jaxbAnnotationModule);
/*AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new XmlJaxbAnnotationIntrospector(mapper.getTypeFactory()); //new JaxbAnnotationIntrospector(mapper.getTypeFactory());
AnnotationIntrospector pair = new AnnotationIntrospectorPair(primary,secondary);
mapper.setAnnotationIntrospector(pair);*/
However, the other 2 are still ignored, resulting in this example xml:
<?xml version="1.0"?>
<EHDTOApplicatorUnits>
<UnitGroup>
<name>string</name>
<unit>
<id>1</id>
<name>string</name>
<unitSystem>string</unitSystem>
</unit>
</UnitGroup>
</EHDTOApplicatorUnits>
While the real output of the API is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ApplicatorUnits>
<UnitGroup name="coefTempErrorSpan">
<unit>
<id>1</id>
<name>% span /10K</name>
<unitSystem>SI</unitSystem>
</unit>
<unit>
<id>2</id>
<name>% span /50F</name>
<unitSystem>SI</unitSystem>
</unit>
</UnitGroup>
...
</ApplicatorUnits>
You see the different naming of the root element, and also the "name" of the UnitGroup which is not an attribute in the example xml but an own child-node.
I found I can use #ApiModel(value = "ApplicatorUnits") as workaround for #XmlRootElement but what about #XmlAttribute, is there also a workaround? #ApiModelProperty does not seem to work for this case. Does somebody have an idea how to workaround this issue?

AppFabric: Could not contact the cache service

Update: I have now implemented this properly. For more information see my blog post about it.
I'm trying to use AppFabric with NHibernate as my second level cache provider but I'm getting the following error: ErrorCode:Initialization: Could not contact the cache service. Contact administrator and refer to product help documentation for possible reasons.
I presume that the problem is with my configuration in web.config:
<section name="dcacheClient"
type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core"
allowLocation="true"
allowDefinition="Everywhere"/>
...
<dcacheClient deployment="routing" localCache="False">
<localCache isEnabled="false" sync="TimeoutBased" ttlValue="300" />
<hosts>
<host name="localhost" cachePort="22233" cacheHostName="AppFabricCachingService" />
</hosts>
</dcacheClient>
I've downloaded the NHibernate.Caches source code to try and discover where the problem lies and the exception is being thrown in the VelocityClient constructor when the GetCache method is called:
public VelocityClient(string regionName, IDictionary<string, string> properties)
{
region = regionName.GetHashCode().ToString(); //because the region name length is limited
var cacheCluster = new CacheFactory();
cache = cacheCluster.GetCache(CacheName);
try
{
cache.CreateRegion(region, true);
}
catch (CacheException) {}
}
If I add a watch to the cacheCluster variable, I can find a _servers private variable which has one System.Data.Caching.EndpointID which has the MyURI property set to net.tcp://localhost:22234/AppFabricCachingServive which I presume has come from the configuration in web.config.
If you don't know the exact cause of the problem but have some ideas on how to go about troubleshooting this problem, that would be much appreciated as well.
Additional Info
I get the following results from the command, Get-CacheHostConfig -HostName tn-staylor-02 -CachePort 22233:
HostName : tn-staylor-02
ClusterPort : 22234
CachePort : 22233
ArbitrationPort : 22235
ReplicationPort : 22236
Size : 3001 MB
ServiceName : AppFabricCachingService
HighWatermark : 90%
LowWatermark : 70%
IsLeadHost : True
So I think the values I've got configured in web.config are OK.
Googling this problem and investigating how to set up AppFabric in the first place, I have come across two slightly different ways of how to configure the cache in web.config. The way I have described above and the way Hanselman has it in his AppFabric blog post
I actually started with it like this however, I got the following error which is how I came to have it configured how I have it now:
ErrorCode:"dcacheClient" tag not specified in the application configuration file. Specify valid tag in configuration file.
Full stack trace of the exception that gets thrown in VelocityClient:
System.Data.Caching.CacheException occurred
Message="ErrorCode:\"dcacheClient\" tag not specified in the application configuration file. Specify valid tag in configuration file."
Source="CacheBaseLibrary"
ErrorCode="ERRCMC0004"
StackTrace:
at System.Data.Caching.ClientConfigFile.ThrowException(String errorCode, String param)
at System.Data.Caching.ClientConfigReader.GetDeployementMode()
at System.Data.Caching.ClientConfigurationManager.InitializeDepMode(ClientConfigReader cfr)
at System.Data.Caching.ClientConfigurationManager.Initialize(String path)
at System.Data.Caching.ClientConfigurationManager..ctor()
at System.Data.Caching.CacheFactory.InitCacheFactory()
at System.Data.Caching.CacheFactory.GetCache(String cacheName)
at NHibernate.Caches.Velocity.VelocityClient..ctor(String regionName, IDictionary`2 properties) in C:\Source\Projects\NHibernate.contrib\trunk\src\NHibernate.Caches\Velocity\NHibernate.Caches.Velocity\VelocityClient.cs:line 67
InnerException:
EDIT: Added output from get-cachehost as requested by #PhilPursglove
Output from get-cachehost:
HostName : CachePort Service Name Service Status Version Info
-------------------- ------------ -------------- ------------
tn-staylor-02:22233 AppFabricCachingService UP 1 [1,1][1,1]
SOLUTION: #PhilPursglove was spot on. The NHibernate velocity provider was using old dll's so upgrading them and making a few code changes resolved my problems. I thought I would include my complete solution here.
Downloaded the NHibernate.contrib source from the SVN repository at https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk
Opened up the NHibernate.Caches.Everything solution and removed the references to the old velocity dll's from the NHibernate.Caches.Velocity project.
Added references to the App Fabric dll's which were installed when I installed App Fabric. This isn't the normal case of adding a reference to an assembly in the GAC, but this article describes how to do it.
Adding the new references meant that the VelocityClient class no longer compiled. With a little bit of help from this I came up with the version of VelocityClient.cs below.
I added a reference to the new version of NHibernate.Caches.Velocity to my project, made the changes below to my configuration and everything worked.
VelocityClient.cs
using System;
using System.Collections.Generic;
using Microsoft.ApplicationServer.Caching;
using log4net;
using NHibernate.Cache;
using CacheException = Microsoft.ApplicationServer.Caching.DataCacheException;
using CacheFactory = Microsoft.ApplicationServer.Caching.DataCacheFactory;
namespace NHibernate.Caches.Velocity
{
public class VelocityClient : ICache
{
private const string CacheName = "nhibernate";
private static readonly ILog log;
private readonly DataCache cache;
private readonly string region;
private Dictionary<string, DataCacheLockHandle> locks = new Dictionary<string, DataCacheLockHandle>();
static VelocityClient()
{
log = LogManager.GetLogger(typeof (VelocityClient));
}
public VelocityClient() : this("nhibernate", null) {}
public VelocityClient(string regionName) : this(regionName, null) {}
public VelocityClient(string regionName, IDictionary<string, string> properties)
{
region = regionName.GetHashCode().ToString(); //because the region name length is limited
var cacheCluster = new CacheFactory();
cache = cacheCluster.GetCache(CacheName);
try
{
cache.CreateRegion(region);
}
catch (CacheException) {}
}
#region ICache Members
public object Get(object key)
{
if (key == null)
{
return null;
}
if (log.IsDebugEnabled)
{
log.DebugFormat("fetching object {0} from the cache", key);
}
DataCacheItemVersion version = null;
return cache.Get(key.ToString(), out version, region);
}
public void Put(object key, object value)
{
if (key == null)
{
throw new ArgumentNullException("key", "null key not allowed");
}
if (value == null)
{
throw new ArgumentNullException("value", "null value not allowed");
}
if (log.IsDebugEnabled)
{
log.DebugFormat("setting value for item {0}", key);
}
cache.Put(key.ToString(), value, region);
}
public void Remove(object key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
if (log.IsDebugEnabled)
{
log.DebugFormat("removing item {0}", key);
}
if (Get(key.ToString()) != null)
{
cache.Remove(region, key.ToString());
}
}
public void Clear()
{
cache.ClearRegion(region);
}
public void Destroy()
{
Clear();
}
public void Lock(object key)
{
DataCacheLockHandle lockHandle = null;
if (Get(key.ToString()) != null)
{
try
{
cache.GetAndLock(key.ToString(), TimeSpan.FromMilliseconds(Timeout), out lockHandle, region);
locks.Add(key.ToString(), lockHandle);
}
catch (CacheException) {}
}
}
public void Unlock(object key)
{
DataCacheLockHandle lockHandle = null;
if (Get(key.ToString()) != null)
{
try
{
if (locks.ContainsKey(key.ToString()))
{
cache.Unlock(key.ToString(), locks[key.ToString()], region);
locks.Remove(key.ToString());
}
}
catch (CacheException) {}
}
}
public long NextTimestamp()
{
return Timestamper.Next();
}
public int Timeout
{
get { return Timestamper.OneMs * 60000; } // 60 seconds
}
public string RegionName
{
get { return region; }
}
#endregion
}
}
NHibernate.config:
...
<property name="cache.provider_class">NHibernate.Caches.Velocity.VelocityProvider, NHibernate.Caches.Velocity</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_query_cache">true</property>
...
web.config
...
<section name="dataCacheClient"
type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
allowLocation="true"
allowDefinition="Everywhere"/>
...
<dataCacheClient>
<!-- cache host(s) -->
<hosts>
<host
name="localhost"
cachePort="22233"/>
</hosts>
</dataCacheClient>
...
I didn't make any further changes to my App Fabric configuration or anything.
I think there are two possible culprits here:
In your web.config under the hosts element, you're listing localhost - I'd try swapping that out for the actual server name tn-staylor-02
That exception stack trace refers to CacheBaseLibrary - I don't know a great deal (read: anything!) about NHibernate but I would hazard a guess that that cache might not be built with the release version of AppFabric - CacheBaseLibrary was an assembly that appeared in the CTPs and betas but I didn't think it was used in the RTM version. Note that in the section element for dcacheclient, it refers to the Microsoft.ApplicationServer.Caching.Core assembly.