I am trying to do UI automation using specflow/CodedUI/VSTS 2012.
When I try to run the scenario, I am getting the following error:
Could not load file or assembly 'Microsoft.VisualStudio.TestTools.UITest.Playback, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
Can anyone tell me how to resolve this error ?
Finally I found a way to resolve this problem. I do not know why but you have to write your own assembly resolver. I found the solution here:
http://blog.csdn.net/marryshi/article/details/8100194
However, I had to update the registry path for VS2012:
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
AssemblyName assemblyName = new AssemblyName(args.Name);
if (assemblyName.Name.StartsWith("Microsoft.VisualStudio.TestTools.UITest", StringComparison.Ordinal))
{
string path = string.Empty;
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\VisualStudio\11.0"))
{
if (key != null)
{
path = key.GetValue("InstallDir") as string;
}
}
if (!string.IsNullOrWhiteSpace(path))
{
string assemblyPath = Path.Combine(path, "PublicAssemblies",
string.Format(CultureInfo.InvariantCulture, "{0}.dll", assemblyName.Name));
if (!File.Exists(assemblyPath))
{
assemblyPath = Path.Combine(path, "PrivateAssemblies",
string.Format(CultureInfo.InvariantCulture, "{0}.dll", assemblyName.Name));
if (!File.Exists(assemblyPath))
{
string commonFiles = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86);
if (string.IsNullOrWhiteSpace(commonFiles))
{
commonFiles = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles);
}
assemblyPath = Path.Combine(commonFiles, "Microsoft Shared", "VSTT", "10.0",
string.Format(CultureInfo.InvariantCulture, "{0}.dll", assemblyName.Name));
}
}
if (File.Exists(assemblyPath))
{
return Assembly.LoadFrom(assemblyPath);
}
}
}
return null;
}
And I registry resolver before running the feature:
[BeforeFeature]
public static void Initialize()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
Related
Hi I have configured the default filter as below and if some emails have a certain subject or from address I try to move them to specific folders using java mail api as below:
Filter implementation:
#Bean(name = ImapAdaptersUtil.DEFAULT_FILTER_BEAN_NAME)
#Scope(WebApplicationContext.SCOPE_APPLICATION)
public MessageSelector defaultFilter() {
return message -> {
if (message.getPayload() instanceof MimeMessage) {
try {
String from = Optional.ofNullable(((InternetAddress) ((MimeMessage) message.getPayload()).getFrom()[0]).getAddress()).orElse(GeneralConst.EMPTY_STRING);
String subject = Optional.ofNullable(((MimeMessage) message.getPayload()).getSubject()).orElse(GeneralConst.EMPTY_STRING);
if (!from.matches(DELIVERY_ERROR_FROM)
&& !from.matches(SPAM_FROM)
&& !subject.matches(DELIVERY_ERROR_SUBJECT)
&& !subject.matches(OUT_OF_OFFICE)
&& !subject.matches(SPAM_SUBJECT)) {
return true;
}
} catch (MessagingException me) {
throw new ApplicationBusinessException(ApplicationBusinessException.ApplicationBusinessExceptionType.FUNCTIONAL_VIOLATION,
"Could not filter incoming email: " + me.getMessage());
}
}
try {
this.moveMessage(((MimeMessage) message.getPayload()));
} catch (MessagingException me) {
throw new ApplicationBusinessException(ApplicationBusinessException.ApplicationBusinessExceptionType.FUNCTIONAL_VIOLATION,
"Could not move incoming email: " + me.getMessage());
}
return false;
};
}
Move to folder implementation:
private void moveMessage(MimeMessage message) throws MessagingException {
Folder folder = message.getFolder();
Store store = folder.getStore();
Folder[] folders = store.getDefaultFolder().list("*");
for (Folder folder1 : folders) {
LOGGER.info("folder name {}", folder1.getName());
}
Folder deliveryErrorFolder = store.getFolder("Delivery error");
if (!deliveryErrorFolder.exists()) {
if (deliveryErrorFolder.create(Folder.HOLDS_MESSAGES)) {
deliveryErrorFolder.setSubscribed(true);
move(message, folder, deliveryErrorFolder);
LOGGER.info("Delivery error created");
}
} else {
move(message, folder, deliveryErrorFolder);
}
}
private void move(MimeMessage message, Folder folder, Folder spamFolder) throws MessagingException {
List<javax.mail.Message> tempList = new ArrayList<>();
tempList.add(message);
javax.mail.Message[] tempMessageArray = tempList.toArray(new javax.mail.Message[0]);
folder.copyMessages(tempMessageArray, spamFolder);
LOGGER.info("message moved");
}
ImapMailReceiver configured as an Integration flow :
public static IntegrationFlow getImapAdapterIntegrationFlow(String imapsUrl, MessageSelector filter, QueueChannelSpec channelSpec) {
return IntegrationFlows
.from(Mail.imapInboundAdapter(imapsUrl)
.userFlag("testSIUserFlag")
.simpleContent(false)
.autoCloseFolder(false)
.shouldMarkMessagesAsRead(true)
.javaMailProperties(getPropertiesBuilderConsumer()),
e -> e.autoStartup(true)
.poller(p -> p.fixedDelay(1000)))
.filter(filter)
.channel(channelSpec)
.get();
}
I get this exception :
Caused by: java.lang.ClassCastException: class org.springframework.integration.mail.AbstractMailReceiver$IntegrationMimeMessage cannot be cast to class com.sun.mail.imap.IMAPMessage (org.springframework.integration.mail.AbstractMailReceiver$IntegrationMimeMessage and com.sun.mail.imap.IMAPMessage are in unnamed module of loader 'app')
at com.sun.mail.imap.Utility.toMessageSet(Utility.java:85)
Yeah... What you are looking for is available starting with version 5.4: https://docs.spring.io/spring-integration/docs/current/reference/html/mail.html#mail-inbound
Starting with version 5.4, it is possible now to return a MimeMessage as is without any conversion or eager content loading. This functionality is enabled with this combination of options: no headerMapper provided, the simpleContent property is false and the autoCloseFolder property is false.
So, all good in your config - only what you need to to upgrade your project to the latest Spring Integration. Directly with the 5.4.5 or via respective latest Spring Boot.
I'm would like to use MOXy to marshal / unmarshal object from existing classes.
I would like to know if there is a mean to generate XML binding files (cause I don't want to use annotations) from my classes.
Or do we have to do it all with our little hands :) ?
By default JAXB/MOXy doesn't require any metadata to be specified (see: http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html). You only need to specify the metadata where you want to override the default behaviour.
I'm guessing your real question is what is the easiest way to create the MOXy external mapping document. I do the following with Eclipse, there are probably similar steps for your favourite IDE:
Get the XML Schema for MOXy's mapping document
<EclipseLink_Home>/xsds/eclipselink_oxm_2_5.xsd
Register the XML Schema with your IDE
Eclipse | Preferences | XML | XML Catalog | Add
Create and XML document in the IDE and specify the following as the root element.
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"/>
Use the auto-complete functionality offered by your IDE to construct the XML document.
Another option is to generate jaxb classes and from those read the bindings (annotations) producing an external mapping (after which you can remove the annotations). PoC code:
public class MoxyBindingGenerator {
private static final String PACKAGE = "com.company.binding.jaxbclasses";
private static ObjectFactory xmlBindingsFactory = new ObjectFactory();
public static void main(String[] args) throws Exception {
Collection<TypeInfo> typeInfos = readAnnotations();
XmlBindings xmlBindings = xmlBindingsFactory.createXmlBindings();
xmlBindings.setPackageName(PACKAGE);
JavaTypes javaTypes = xmlBindingsFactory.createXmlBindingsJavaTypes();
xmlBindings.setJavaTypes(javaTypes);
List<JavaType> javaTypesList = javaTypes.getJavaType();
XmlEnums xmlEnums = xmlBindingsFactory.createXmlBindingsXmlEnums();
xmlBindings.setXmlEnums(xmlEnums);
List<XmlEnum> xmlEnumsList = xmlEnums.getXmlEnum();
typeInfos.stream().forEach(typeInfo -> {
if (!typeInfo.isEnumerationType()) {
fillJavaTypes(javaTypesList, typeInfo);
}
else {
fillEnumTypes(xmlEnumsList, typeInfo);
}
});
saveToFile(xmlBindings);
}
private static Collection<TypeInfo> readAnnotations() throws JAXBException, Exception {
JAXBContext jaxbContext = (JAXBContext) javax.xml.bind.JAXBContext.newInstance(PACKAGE);
Object contextState = getPrivateField(jaxbContext, "contextState");
Generator generator = (Generator) getPrivateField(contextState, "generator");
AnnotationsProcessor annotationsProcessor = generator.getAnnotationsProcessor();
Collection<TypeInfo> typeInfos = annotationsProcessor.getTypeInfo().values();
return typeInfos;
}
private static void fillEnumTypes(List<XmlEnum> xmlEnumsList, TypeInfo typeInfo) {
EnumTypeInfo et = (EnumTypeInfo) typeInfo;
XmlEnum xmlEnum = xmlBindingsFactory.createXmlEnum();
xmlEnum.setJavaEnum(et.getJavaClassName());
List<String> xmlEnumNames = et.getFieldNames();
List<Object> xmlEnumValues = et.getXmlEnumValues();
for (int i = 0; i < xmlEnumNames.size(); i++) {
String xmlEnumName = xmlEnumNames.get(i);
Object xmlEnumObject = xmlEnumValues.get(i);
XmlEnumValue xmlEnumValue = xmlBindingsFactory.createXmlEnumValue();
xmlEnumValue.setJavaEnumValue(xmlEnumName);
xmlEnumValue.setValue(xmlEnumObject.toString());
xmlEnum.getXmlEnumValue().add(xmlEnumValue);
}
xmlEnumsList.add(xmlEnum);
}
private static void fillJavaTypes(List<JavaType> javaTypesList, TypeInfo typeInfo) {
JavaType javaType = xmlBindingsFactory.createJavaType();
javaType.setName(typeInfo.getJavaClassName());
fillXmlType(javaType, typeInfo);
if (typeInfo.getXmlRootElement() != null) {
XmlRootElement xmlRootElement = typeInfo.getXmlRootElement();
xmlRootElement.setNamespace(null);
javaType.setXmlRootElement(xmlRootElement);
}
JavaAttributes javaAttributes = xmlBindingsFactory.createJavaTypeJavaAttributes();
javaType.setJavaAttributes(javaAttributes);
List<JAXBElement<? extends JavaAttribute>> javaAttributeList = javaAttributes.getJavaAttribute();
typeInfo.getNonTransientPropertiesInPropOrder().stream().forEach(field -> {
fillFields(javaAttributeList, field);
});
javaTypesList.add(javaType);
}
private static void fillFields(List<JAXBElement<? extends JavaAttribute>> javaAttributeList, Property field) {
if (field.getXmlElements() != null && field.getXmlElements().getXmlElement().size() > 0) {
XmlElements xmlElements = xmlBindingsFactory.createXmlElements();
xmlElements.setJavaAttribute(field.getPropertyName());
List<XmlElement> elements = field.getXmlElements().getXmlElement();
elements.stream().forEach(e -> {
e.setDefaultValue(null);
e.setNamespace(null);
xmlElements.getXmlElement().add(e);
});
JAXBElement<XmlElements> value = xmlBindingsFactory.createXmlElements(xmlElements);
javaAttributeList.add(value);
}
else if (!field.isAttribute()) {
XmlElement value = xmlBindingsFactory.createXmlElement();
value.setJavaAttribute(field.getPropertyName());
value.setName(field.getSchemaName().getLocalPart());
if (field.isNillable())
value.setNillable(field.isNillable());
if (field.isRequired())
value.setRequired(field.isRequired());
javaAttributeList.add(xmlBindingsFactory.createXmlElement(value));
}
else {
XmlAttribute value = xmlBindingsFactory.createXmlAttribute();
value.setJavaAttribute(field.getPropertyName());
value.setName(field.getSchemaName().getLocalPart());
javaAttributeList.add(xmlBindingsFactory.createXmlAttribute(value));
}
}
private static void saveToFile(XmlBindings xmlBindings)
throws JAXBException, PropertyException, FileNotFoundException, IOException {
JAXBContext xmlModelJaxbContext =
(JAXBContext) javax.xml.bind.JAXBContext.newInstance("org.eclipse.persistence.jaxb.xmlmodel");
JAXBMarshaller marshaller = xmlModelJaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
FileOutputStream fos = new FileOutputStream(new File(System.getProperty("user.home"), "binding-imspoor-oxm.xml"));
marshaller.marshal(xmlBindings, fos);
fos.close();
}
private static void fillXmlType(JavaType javaType, TypeInfo typeInfo) {
XmlType orgXmlType = typeInfo.getXmlType();
if (orgXmlType != null) {
boolean add = false;
XmlType xmlType = xmlBindingsFactory.createXmlType();
if (!StringUtils.isEmpty(orgXmlType.getName())) {
xmlType.setName(orgXmlType.getName());
add = true;
}
if (orgXmlType.getPropOrder() != null && orgXmlType.getPropOrder().size() > 1) {
xmlType.getPropOrder().addAll(orgXmlType.getPropOrder());
add = true;
}
if (add)
javaType.setXmlType(xmlType);
}
}
private static Object getPrivateField(Object obj, String fieldName) throws Exception {
Field declaredField = obj.getClass().getDeclaredField(fieldName);
declaredField.setAccessible(true);
return declaredField.get(obj);
}
}
I'm currently working on creating a namespace extension.
So I want to create an entry in Computer, and had explorer.exe calling my IShellFolder implementation.
I had it working for few minutes (I stupidly decided to clean up the code before commiting), so I'm somewhere near.
But I noticed something very strange: changing the GUID value of the Class change what I see in explorer.exe
I found that question which tells me I am not doing something bad
Here's the code:
AssemblyInfo.cs:
[assembly: ComVisible(false)]
[assembly: Guid("007C5100-4251-47BE-8141-D2AD3F496E6A")]
RootFolder.cs:
[ClassInterface(ClassInterfaceType.None)
[Guid("007C5101-4251-47BE-8141-D2AD3F496E6A"), ComVisible(true)]
public class RootFolder : IShellFolder, IShellFolder2, IPersistFolder, IPersistFolder2 {
private const String _mountPoint = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\NameSpace\\{0}";
private const String _mountName = "CLSID\\{0}";
#region Shell Extension Registration
[ComRegisterFunction()]
public static void Register(Type t)
{
Console.WriteLine("Registering {0}...", t.GUID);
try {
if (t.GUID == null)
throw new ArgumentException("CLSID must not be null");
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(String.Format(_mountPoint, t.GUID.ToString("B")))) {
key.SetValue(null, "RootFolder");
}
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(String.Format(_mountName, t.GUID.ToString("B")), true)) {
key.SetValue(null, "RootFolder");
using (RegistryKey shFolder = key.CreateSubKey("ShellFolder")) {
shFolder.SetValue("Attributes", 0x78000040);
shFolder.SetValue("WantsFORPARSING", "");
}
}
using (RegistryKey key = Registry.LocalMachine.CreateSubKey(#"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved")) {
key.SetValue(t.GUID.ToString("B"), "RootFolder");
}
IntPtr pidl = NativeMethod.SHGetKnownFolderIDList(KnownFolder.ComputerFolder.clsid, 0, IntPtr.Zero);
NativeMethod.SHChangeNotify(NativeMethod.FSNotification.UpdateDir, NativeMethod.ItemMeaning.IDList, pidl, IntPtr.Zero);
} catch (Exception ex) {
Logger.Write(Logger.Severity.Fatal, "Registration error: {0}", ex.Message);
throw; // Re-throw the exception
}
}
[ComUnregisterFunction()]
public static void Unregister(Type t)
{
try {
if (t.GUID == null)
throw new ArgumentException("CLSID must not be null");
Registry.CurrentUser.DeleteSubKey(String.Format(_mountPoint, t.GUID.ToString("B")), false);
using (RegistryKey k = Registry.ClassesRoot.OpenSubKey(String.Format(_mountName, t.GUID.ToString("B")), true)) {
if (k != null)
k.DeleteSubKey("ShellFolder");
}
using (RegistryKey key = Registry.LocalMachine.CreateSubKey(#"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved")) {
if (key != null)
key.DeleteValue(t.GUID.ToString("B"), false);
}
IntPtr pidl = NativeMethod.SHGetKnownFolderIDList(KnownFolder.ComputerFolder.clsid, 0, IntPtr.Zero);
NativeMethod.SHChangeNotify(NativeMethod.FSNotification.UpdateDir, NativeMethod.ItemMeaning.IDList, pidl, IntPtr.Zero);
} catch (Exception ex) {
Logger.Write(Logger.Severity.Critical, "Registration error: {0}", ex.Message);
throw; // Re-throw the exception
}
}
#endregion
#region IShellFolder2 Inheritance
[All the methods looks like that, this is just a test]
public IEnumIDList EnumObjects(IntPtr hwndOwner, EnumObject flags)
{
Logger.Write("Tracing....");
throw new NotImplementedException();
}
#endregion
#region IPersistFolder2 Inheritance
[Ditto]
#endregion
}
I use the range 007C5{100...120}-4251-47BE-8141-D2AD3F496E6A for my GUIDs
When my extension has GUID 007C5101, it just shows "RootFolder" without any attributes.
When it has 007C5100 (same as assembly), or 007C5102, or 007C5103, it is shown as "System Folder" (even though it doesnt call my DLL).
I'm a little puzzled by this behaviour, how in the world can changing a GUID lead to this change ?
Note: I ran a search through the registry for 4251-47BE-8141-D2AD3F496E6A (the immutable part of my GUID), and couldn't find anything after unregistration.
I'm using the ASP.NET MVC 4 bundling and minifying features in the Microsoft.AspNet.Web.Optimization namespace (e.g. #Styles.Render("~/content/static/css")).
I'd like to use it in combination with a Windows Azure CDN.
I looked into writing a custom BundleTransform but the content is not optimized there yet.
I also looked into parsing and uploading the optimized stream on runtime but that feels like a hack to me and I don't really like it:
#StylesCdn.Render(Url.AbsoluteContent(
Styles.Url("~/content/static/css").ToString()
));
public static IHtmlString Render(string absolutePath)
{
// get the version hash
string versionHash = HttpUtility.ParseQueryString(
new Uri(absolutePath).Query
).Get("v");
// only parse and upload to CDN if version hash is different
if (versionHash != _versionHash)
{
_versionHash = versionHash;
WebClient client = new WebClient();
Stream stream = client.OpenRead(absolutePath);
UploadStreamToAzureCdn(stream);
}
var styleSheetLink = String.Format(
"<link href=\"{0}://{1}/{2}/{3}?v={4}\" rel=\"stylesheet\" type=\"text/css\" />",
cdnEndpointProtocol, cdnEndpointUrl, cdnContainer, cdnCssFileName, versionHash
);
return new HtmlString(styleSheetLink);
}
How can I upload the bundled and minified versions automatically to my Windows Azure CDN?
Following Hao's advice I Extended Bundle and IBundleTransform.
Adding AzureScriptBundle or AzureStyleBundle to bundles;
bundles.Add(new AzureScriptBundle("~/bundles/modernizr.js", "cdn").Include("~/Scripts/vendor/modernizr.custom.68789.js"));
Results in;
<script src="//127.0.0.1:10000/devstoreaccount1/cdn/modernizr.js?v=g-XPguHFgwIb6tGNcnvnI_VY_ljCYf2BDp_NS5X7sAo1"></script>
If CdnHost isn't set it will use the Uri of the blob instead of the CDN.
Class
using System;
using System.Text;
using System.Web;
using System.Web.Optimization;
using System.Security.Cryptography;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
namespace SiegeEngineWebRole.BundleExtentions
{
public class AzureScriptBundle : Bundle
{
public AzureScriptBundle(string virtualPath, string containerName, string cdnHost = "")
: base(virtualPath, null, new IBundleTransform[] { new JsMinify(), new AzureBlobUpload { ContainerName = containerName, CdnHost = cdnHost } })
{
ConcatenationToken = ";";
}
}
public class AzureStyleBundle : Bundle
{
public AzureStyleBundle(string virtualPath, string containerName, string cdnHost = "")
: base(virtualPath, null, new IBundleTransform[] { new CssMinify(), new AzureBlobUpload { ContainerName = containerName, CdnHost = cdnHost } })
{
}
}
public class AzureBlobUpload : IBundleTransform
{
public string ContainerName { get; set; }
public string CdnHost { get; set; }
static AzureBlobUpload()
{
}
public virtual void Process(BundleContext context, BundleResponse response)
{
var file = VirtualPathUtility.GetFileName(context.BundleVirtualPath);
if (!context.BundleCollection.UseCdn)
{
return;
}
if (string.IsNullOrWhiteSpace(ContainerName))
{
throw new Exception("ContainerName Not Set");
}
var conn = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));
var blob = conn.CreateCloudBlobClient()
.GetContainerReference(ContainerName)
.GetBlobReference(file);
blob.Properties.ContentType = response.ContentType;
blob.UploadText(response.Content);
var uri = string.IsNullOrWhiteSpace(CdnHost) ? blob.Uri.AbsoluteUri.Replace("http:", "").Replace("https:", "") : string.Format("//{0}/{1}/{2}", CdnHost, ContainerName, file);
using (var hashAlgorithm = CreateHashAlgorithm())
{
var hash = HttpServerUtility.UrlTokenEncode(hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(response.Content)));
context.BundleCollection.GetBundleFor(context.BundleVirtualPath).CdnPath = string.Format("{0}?v={1}", uri, hash);
}
}
private static SHA256 CreateHashAlgorithm()
{
if (CryptoConfig.AllowOnlyFipsAlgorithms)
{
return new SHA256CryptoServiceProvider();
}
return new SHA256Managed();
}
}
}
So there isn't a great way to do this currently. The longer term workflow we are envisioning is adding build-time bundling support. Then you would run a build task (or run an exe if you prefer) to generate the bundles and then be able to upload these to the AzureCDN. Finally, you just turn on UseCDN on the BundleCollection, and the Script/Style helpers would just automatically switch to rendering out links to your AzureCDN with proper fallback to your local bundles.
For the short term, what I think you are trying to do is upload your bundle to the AzureCDN when the bundle is first constructed?
A BundleTransform is one way to do it I guess, its a bit of a hack, but you could add a BundleTransform last in your bundle. Since its last, the BundleResponse.Content is effectively the final bundle response. At that point in time you can upload it to your CDN. Does that make sense?
You can define origin domain as Azure's website (this probably was added long after the original question).
Once you have CDN endpoint, you will need to allow query string for it and then you can reference directly to bundles via CDN:
<link href="//az888888.vo.msecnd.net/Content/css-common?v=ioYVnAg-Q3qYl3Pmki-qdKwT20ESkdREhi4DsEehwCY1" rel="stylesheet"/>
I've also created this helper to append CDN host name:
public static IHtmlString RenderScript(string virtualPath)
{
if (HttpContext.Current.IsDebuggingEnabled)
return Scripts.Render(virtualPath);
else
return new HtmlString(String.Format(
CultureInfo.InvariantCulture,
Scripts.DefaultTagFormat,
"//CDN_HOST" + Scripts.Url(virtualPath).ToHtmlString()));
}
For #manishKungwani requested in previous comment. Just set UseCdn and then use the
cdnHost overload to crate the bundle. I used this to put in an AWS CloudFront domain (xxx.cloudfront.net) but in hindsight it should have been named more generically to use with any other CDN provider.
public class CloudFrontScriptBundle : Bundle
{
public CloudFrontScriptBundle(string virtualPath, string cdnHost = "")
: base(virtualPath, null, new IBundleTransform[] { new JsMinify(), new CloudFrontBundleTransformer { CdnHost = cdnHost } })
{
ConcatenationToken = ";";
}
}
public class CloudFrontStyleBundle : Bundle
{
public CloudFrontStyleBundle(string virtualPath, string cdnHost = "")
: base(virtualPath, null, new IBundleTransform[] { new CssMinify(), new CloudFrontBundleTransformer { CdnHost = cdnHost } })
{
}
}
public class CloudFrontBundleTransformer : IBundleTransform
{
public string CdnHost { get; set; }
static CloudFrontBundleTransformer()
{
}
public virtual void Process(BundleContext context, BundleResponse response)
{
if (context.BundleCollection.UseCdn && !String.IsNullOrWhiteSpace(CdnHost))
{
var virtualFileName = VirtualPathUtility.GetFileName(context.BundleVirtualPath);
var virtualDirectory = VirtualPathUtility.GetDirectory(context.BundleVirtualPath);
if (!String.IsNullOrEmpty(virtualDirectory))
virtualDirectory = virtualDirectory.Trim('~');
var uri = string.Format("//{0}{1}{2}", CdnHost, virtualDirectory, virtualFileName);
using (var hashAlgorithm = CreateHashAlgorithm())
{
var hash = HttpServerUtility.UrlTokenEncode(hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(response.Content)));
context.BundleCollection.GetBundleFor(context.BundleVirtualPath).CdnPath = string.Format("{0}?v={1}", uri, hash);
}
}
}
private static SHA256 CreateHashAlgorithm()
{
if (CryptoConfig.AllowOnlyFipsAlgorithms)
{
return new SHA256CryptoServiceProvider();
}
return new SHA256Managed();
}
}
i wrote like the following code.
but this code is not available...
when i execute, occur.
if anyone knows something, give me advice pls...
thanks in advance.
void sftp_OnTransferEnd(string src, string dst, int transferredBytes
, int totalBytes, string message)
{
if (sftp == null)
{
sftp = new Sftp(Const.SFTP_HOST, Const.SFTP_USER, Const.SFTP_PASSWORD);
sftp.Connect();
}
SftpChannel.rename("file/123_Uploading.zip", "file/123_Finished.zip");
}
--------------------------------------------
Sftp.cs
public void Rename(string oldPath, string newPath)
{
SftpChannel.rename(oldPath, newPath);
}
---------------------------------------------
Error occur the following place...
---------------------------------------------------------
ChannelSftp.cs
public void rename(String oldpath, String newpath)
{
・
・
・
int i=buf.getInt(); << i == 4
if(i==SSH_FX_OK) return;
throwStatusError(buf, i); << throw error
catch(Exception e)
{
if(e is SftpException) throw (SftpException)e; << thrown error (id >> 4, message >> Failure)
throw new SftpException(SSH_FX_FAILURE, "");
}
}
The current NuGet package is still of version 1.1.1.13 which does not contain the Rename method. It would be great if the package maintainer could update it.
But in the meantime if anyone else needs it with the current NuGet package, here is a Reflection-based extension method solution. Not nice, but at least I can use the package without forking/rebuilding, etc.
public static void Rename(this Sftp client, string oldName, string newName) {
var channelProperty = client.GetType().GetProperty("SftpChannel", BindingFlags.NonPublic | BindingFlags.Instance);
channelProperty.GetValue(_client, null).CastTo<ChannelSftp>().rename(OldName, newName);
}
I added your
public void Rename(string oldPath, string newPath)
{
SftpChannel.rename(oldPath, newPath);
}
code into Sftp.cs class and I called it :
var sftp = new Sftp("sftp.example.com", username, password);
sftp.Connect(22);
sftp.Rename(oldValue, newValue);
sftp.Close();
then it renamed my file successfully.Thanks by the way