I am running appium on a mac and running the code on an different machine. all good in that is open the simulator etc. However my test still fails as it never goes into the test. The driver variable below evaluates to null and it does not pick it up. Can you help
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium.Appium.iOS;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Enums;
using System.Threading;
using OpenQA.Selenium.Support.UI;
namespace AutoItX_Testing
{
[TestFixture]
class IOSDemo
{
public IOSDriver<IOSElement> driver;
// public IWebDriver driver;
[SetUp]
public void Start()
{
//Setting Capabilities
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability(MobileCapabilityType.PlatformVersion, "10.1");
//capabilities.SetCapability("platform", "Mac");
// capabilities.SetCapability("deviceName", "iPhone 6");
capabilities.SetCapability(MobileCapabilityType.DeviceName, "iPhone 6");
capabilities.SetCapability(MobileCapabilityType.AutomationName, "XCUITest");
capabilities.SetCapability(IOSMobileCapabilityType.BundleId, "com.softworks.selfservice.app");
//capabilities.SetCapability("native-instruments-lib", true);
//capabilities.SetCapability("deviceReadyTimeout",100000);
// capabilities.SetCapability("deviceReadyTimeout", "100000");
// capabilities.SetCapability("newCommandTimeout", "18000000000000");
// capabilities.SetCapability("newCommandTimeout", 18000000000000);
capabilities.SetCapability(MobileCapabilityType.PlatformName, "IOS");
capabilities.SetCapability(IOSMobileCapabilityType.LocationServicesEnabled, "false");
capabilities.SetCapability(MobileCapabilityType.NewCommandTimeout, "900000");
capabilities.SetCapability(MobileCapabilityType.NewCommandTimeout, 900000);
capabilities.SetCapability(IOSMobileCapabilityType.LaunchTimeout, "50000");
capabilities.SetCapability(IOSMobileCapabilityType.LaunchTimeout, 50000);
capabilities.SetCapability(IOSMobileCapabilityType.NativeInstrumentsLib, true);
// capabilities.SetCapability(MobileCapabilityType.App, "/Users/itsoftworks/Desktop/UICatalog7/UICatalog.app");
capabilities.SetCapability(MobileCapabilityType.App, "/Users/itsoftworks/Desktop/SelfService/Self Service.app");
driver = new IOSDriver<IOSElement>(
new Uri("http://192.168.17.85:4723/wd/hub"),
capabilities);
while (driver ==null)
{
Thread.Sleep(5000);
Console.WriteLine("driver is still null");
}
// driver = new RemoteWebDriver(new Uri("http://192.168.17.85:4723/wd/hub"),capabilities);
// Thread.Sleep(1000000000);
// driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1000000));
}
[Test]
public void VerifyMenuSimulator()
{
//Test to login into app
Thread.Sleep(100);
Console.WriteLine("it worked"); ;
//driver.manage().Timeouts().ImplicitlyWait(Timespan.FromSeconds(60));
//driver.FindElement(By.XPath("//UIATextField[1]")).SendKeys("username");
// driver.FindElement(By.XPath("///UIASecureTextField[1]")).SendKeys("password");
// driver.FindElement(By.XPath("///UIAButton[1]")).Click();
}
[TearDown]
public void Cleanup()
{
driver.Quit();
}
}
}
Related
I am trying to execute Xamarin App.
I can build and deploy solutions on both Android and iOS devices. But when I am Debugging/running iOS App I am receiving an error
**System.NullReferenceException:** 'Object reference not set to an instance of an object'
on
private static ILogger logger = DependencyService.Get<ILogManager>().GetLog(); line
I have installed the latest version of the Nlog NuGet Package.
My ILogManager file is
namespace VolMobile.AppData.Interfaces
{
public interface ILogManager
{
ILogger GetLog([System.Runtime.CompilerServices.CallerFilePath]string callerFilePath = "");
void Reload();
void DeleteLog();
}
}
How can I resolve this issue?
update
My NLogManager iOS file
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using System.IO;
using NLog;
using NLog.Config;
using NLog.Targets;
using VolMobile.AppData.Interfaces;
using VolMobile.iOS.Logging;
[assembly: Dependency(typeof(NLogManager))]
namespace VolMobile.iOS.Logging
{
public class NLogManager : ILogManager
{
string logFile;
LoggingConfiguration config;
public NLogManager()
{
Reload();
}
public void Reload()
{
config = new LoggingConfiguration();
var consoleTarget = new ConsoleTarget();
config.AddTarget("console", consoleTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
config.LoggingRules.Add(consoleRule);
//File logging level
LogLevel llSetting = LogLevel.Off;
IEnumerable<LogLevel> sysLevels = LogLevel.AllLevels;
//default to trace at startup
string currentLogLevel = "Trace";
//load the app state if available
if (App.AppState != null)
currentLogLevel = App.AppState.AppSettings.LogLevel;// AppData.AppData.LogLevel;
foreach (LogLevel ll in sysLevels)
{
if (currentLogLevel == ll.Name)
{
llSetting = ll;
}
}
var fileTarget = new FileTarget();
string folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); //android.os.environment is the other option
fileTarget.FileName = Path.Combine(folder, "Log.txt");
fileTarget.Layout = "${longdate}|${level:uppercase=true}|${callsite}|${appdomain}|${logger}|${threadid}|${message}|{exception:format=tostring}";
config.AddTarget("file", fileTarget);
logFile = Path.Combine(folder, "Log.txt");
var fileRule = new LoggingRule("*", llSetting, fileTarget);//LogLevel.Warn
config.LoggingRules.Add(fileRule);
LogManager.Configuration = config;
}
public void DeleteLog()
{
File.Delete(logFile);
}
// Services.Logging.ILogger
//AppData.Interfaces.ILogger
//public NLogLogger GetLog([System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "")
//{
// string fileName = callerFilePath;
// if (fileName.Contains("/"))
// {
// fileName = fileName.Substring(fileName.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase) + 1);
// }
// var logger = LogManager.GetLogger(fileName);
// return new NLogLogger(logger, logFile);
//}
public AppData.Interfaces.ILogger GetLog([System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "")
{
string fileName = callerFilePath;
if (fileName.Contains("/"))
{
fileName = fileName.Substring(fileName.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase) + 1);
}
var logger = LogManager.GetLogger(fileName);
return new NLogLogger(logger, logFile);
}
}
}
The app is working perfectly fine on iOS, Andriod simulators, and Android Device only not on iOS devices.
We had CefSharp calling a project deployed on IIS. That worked. And a cookie I need for the third party library is loaded successfully.
Now we want CefSharp to load the same html and third party library through disk, bypassing IIS. Files are loading and running complete with functioning javascript, however the third party library requires a "domain name" to match the one associated with the license.
I need my domain name to match the one on my license which was generated with domain=localhost. But once I specify a domain name, the page, including the license checker, doesn't load.
This is a related problem. A cookie I need to load loads succesfully when I use csharp to call the IIS project, but fails when I open up the html project from disk. For reference, static void FrameLoaded is the same cookie loading procedure used in both versions of my project.
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MinRepExample2
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
namespace MinRepExample2
{
public partial class Form1 : Form
{
private ChromiumWebBrowser browser;
public Form1()
{
InitializeComponent();
try
{
string siteURL = "";
string FileBase = #"c:\users\romero.ryan\documents\visual studio 2015\Projects\MinRepExample2";
string CacheDir = FileBase+#"\Cef2";
// CefSettings to temporarily reduce security
CefSettings MySettings = new CefSettings();
MySettings.CachePath = CacheDir;
MySettings.CefCommandLineArgs.Add("enable-media-stream", "enable-media-stream");
MySettings.CefCommandLineArgs.Add("allow-file-access-from-files", "allow-file-access-from-files");
MySettings.CefCommandLineArgs.Add("disable-web-security", "disable-web-security");
MySettings.JavascriptFlags = "--expose-wasm";
// Browser Settings
BrowserSettings browserSettings = new BrowserSettings();
browserSettings.FileAccessFromFileUrls = CefState.Enabled;
browserSettings.LocalStorage = CefState.Enabled;
browserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
browserSettings.WebSecurity = CefState.Disabled;
// Custom Scheme Registration
MySettings.RegisterScheme(new CefCustomScheme
{
SchemeName = MySchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new MySchemeHandlerFactory(),
IsFetchEnabled = true,
IsLocal = false,
IsCorsEnabled = true,
IsSecure = true,
//DomainName= #"\Users\romero.ryan"
DomainName = "localhost"
});
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
if (!Cef.IsInitialized)
{
Cef.Initialize(MySettings);
}
//string fName = #"C:\Users\romero.ryan\Documents\Visual Studio 2015\Projects\WinHostScandit1\WebHostOnDisk\CefPrimeFiles";
//c:\users\romero.ryan\documents\visual studio 2015\Projects\MinRepExample2\TestSite.html
browser = new ChromiumWebBrowser(#"fileProtocol:\\" + FileBase + "\\TestSite.html");
browser.BrowserSettings = browserSettings;
browser.Dock = DockStyle.Fill;
browser.Name = "browser";
browser.LoadingStateChanged += FrameLoaded;
this.Controls.Add(browser);
}
catch (Exception ex)
{
throw ex;
}
}
public void FrameLoaded(object sender, LoadingStateChangedEventArgs e)
{
//ChromiumWebBrowser ans = (ChromiumWebBrowser)Controls.Find("browser", false).First();
if (!e.IsLoading)
{
// CefSharp specific Cookie manipulation to register app as single device used with Scandit Library.
// ADD Cookie in C# code. Also adding in javascript code
var cookman = browser.GetCookieManager();
string[] schemes = { "fileProtocol", "fileprotocol", "fileprotocol:", "fileProtocol:" };
cookman.SetSupportedSchemes(schemes, true);
CefSharp.Cookie cook1 = new CefSharp.Cookie();
cook1.Domain = "localhost";
cook1.Name = "scandit-device-id";
cook1.Value = "ffaf4f340998d137fc260d563004eabcd388e90f";
cook1.Path = "/scanditpage";
cook1.Expires = new DateTime(2029, 6, 17);
// cookman.SetCookieAsync(ConfigurationManager.AppSettings["ScanditURL"], cook1);
var respcook = cookman.SetCookieAsync("http://localhost/scanditpage/ScanditTest.html", cook1);
bool cookieSet = cookman.SetCookie("http://localhost/scanditpage/ScanditTest.html", cook1);
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
//cookman.SetCookie
// Adding Test cookie
browser.ExecuteScriptAsync("TestAddCookie()");
// Launches Dev tools for Debugging Purposes.
browser.ShowDevTools();
}
}
}
}
MySchemeHandler.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
using System.IO;
namespace MinRepExample2
{
public class MySchemeHandler : ResourceHandler
{
public const string SchemeName = "fileProtocol";
private string folderPath;
public MySchemeHandler()
{
folderPath = "";
}
public override CefSharp.CefReturnValue ProcessRequestAsync(IRequest request, ICallback callback)
{
var uri = new Uri(request.Url);
string fileName = uri.LocalPath;
var requestedFilePath = "C:/" + fileName;
string bFileName = "";
bFileName = requestedFilePath;
if (File.Exists(bFileName))
{
byte[] bytes = File.ReadAllBytes(bFileName);
Stream = new MemoryStream(bytes);
var fileExtension = Path.GetExtension(bFileName);
MimeType = GetMimeType(fileExtension);
return CefReturnValue.Continue;
//return true;
}
else
{
throw new FileNotFoundException();
}
callback.Dispose();
return CefReturnValue.Continue;
}
}
}
MySchemeHandlerFactory:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
namespace MinRepExample2
{
public class MySchemeHandlerFactory: ISchemeHandlerFactory
{
public const string SchemeName = "fileProtocol";
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
return new MySchemeHandler();
}
}
}
Testing HTML:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Test Site for CefSharp Cookies</title>
<script type="text/javascript">
function AddCookie(name, value) {
// Add cookie as name value pair.
var newcookie = name + "=" + value + ";";
document.cookie=newcookie
}
function TestAddCookie() {
// Add specific cookie. Called from executescript in FrameLoaded method
AddCookie("name", "everlast");
}
function ButtonCookie() {
//Adds cookie by button click, then displays all available cookies.
AddCookie("button", "clicked");
var decodedCookie = decodeURIComponent(document.cookie);
alert(decodedCookie);
}
</script>
</head>
<body>
<div>Hello, World!</div>
<button onclick="ButtonCookie();">Add Cookie</button>
</body>
</html>
I figured it out from advice from amaitland and this answer: Simple Custom Scheme.
CefSettings allows you to set permissions like allowing CORS and Fetch for loading WASM files. CefSettings is also used for registering custom scheme handlers. Some schemes might need special permissions to load dependent javascript libraries. Permissions associated with this variable must be set before calling Cef.Initialize. Cef.Initialize should not be called after new ChromiumWebBrowser();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using CefSharp.SchemeHandler;
namespace EpmsMobileWF.ScanditWebForm
{
public partial class ScanditPopupForm : Form
{
public static ScanditPopupConfig scanditConfigs;
public static JSObj1 mess;
public ChromiumWebBrowser browser;
public ScanditPopupForm(TextBox inForm)
{
InitializeComponent();
InitScanner();
mess = new JSObj1(inForm, this);
}
public void InitScanner()
{
scanditConfigs = new ScanditPopupConfig();
var settings = new CefSettings();
FolderSchemeHandlerFactory newFac = new FolderSchemeHandlerFactory(scanditConfigs.HTMLRootFolder,null, scanditConfigs.DomainName, "ScanditTest.html");
CefCustomScheme ScanditScheme = new CefCustomScheme
{
SchemeName = "http",
DomainName = scanditConfigs.DomainName,
SchemeHandlerFactory = newFac,
};
ScanditScheme.IsCorsEnabled = true;
ScanditScheme.IsFetchEnabled = true;
ScanditScheme.IsLocal = true;
ScanditScheme.IsStandard = true;
settings.CachePath = scanditConfigs.ScanditCacheDirectory;
settings.CefCommandLineArgs.Add("enable-media-stream", "enable-media-stream");
settings.CefCommandLineArgs.Add("allow-file-access-from-files", "allow-file-access-from-files");
settings.PersistSessionCookies = true;
settings.JavascriptFlags = "--expose-wasm";
settings.RegisterScheme(ScanditScheme);
Cef.Initialize(settings);
browser = new ChromiumWebBrowser(scanditConfigs.ScanditURL);
this.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
}
}
}
I'm develop cross-platform mobile application that use NFC. I already check the xamarin android beam sample here. Now i'm trying implement the same sample using xamarin forms so i'm using dependency service to call the function from android project.
I already create Ndef message and send function:
using System;
using System.Text;
using Android.App;
using MyApp.Droid;
using Android.Nfc;
using Xamarin.Forms;
[assembly: Dependency(typeof(PhoneBeam))]
namespace MyApp.Droid
{
public class PhoneBeam : Activity, NfcAdapter.ICreateNdefMessageCallback, NfcAdapter.IOnNdefPushCompleteCallback, iBeam
{
private NfcAdapter nfcAdapter;
public void Beam()
{
nfcAdapter = NfcAdapter.GetDefaultAdapter(MainActivity.Instance);
nfcAdapter.SetNdefPushMessageCallback(this, MainActivity.Instance);
nfcAdapter.SetOnNdefPushCompleteCallback(this, MainActivity.Instance);
}
public NdefMessage CreateNdefMessage(NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" + "Beam : " +
time.ToString("HH:mm:ss"));
NdefMessage msg = new NdefMessage(
new NdefRecord[]{ CreateMimeRecord (
"application/com.companyname.MyApp",
Encoding.UTF8.GetBytes (text)) });
return msg;
}
public NdefRecord CreateMimeRecord(String mimeType, byte[] payload)
{
byte[] mimeBytes = Encoding.UTF8.GetBytes(mimeType);
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TnfMimeMedia, mimeBytes, new byte[0], payload);
return mimeRecord;
}
public void OnNdefPushComplete(NfcEvent e){}
}
}
However, I really don't know how to receive a message. In android beam sample, they implement it in mainactivity. Here's sample:
protected override void OnResume ()
{
base.OnResume ();
if (NfcAdapter.ActionNdefDiscovered == Intent.Action) {
ProcessIntent (Intent);
}
}
void ProcessIntent (Intent intent)
{
IParcelable [] rawMsgs = intent.GetParcelableArrayExtra (
NfcAdapter.ExtraNdefMessages);
NdefMessage msg = (NdefMessage) rawMsgs [0];
mInfoText.Text = Encoding.UTF8.GetString (msg.GetRecords () [0].GetPayload ());
}
So i want to implement in class file so i can use dependencyService. Is there a way to implement this?
Edit: I did the send function:
public NdefMessage CreateNdefMessage (NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" +
"Beam Time: " + time.ToString ("HH:mm:ss"));
NdefMessage msg = new NdefMessage (
new NdefRecord[] { CreateMimeRecord (
"application/com.companyname.MyApp", Encoding.UTF8.GetBytes (text))
});
return msg;
}
But it return as "NEW TAG COLLECTED: application/com.companyname.MyApp". I want to resume MyApp and show the message. But it didn't.
I am developing an application, which requires chrome browser history. I have written a C# code for fetching the history. However there are two issues in my code which I am unable to figure out.
There is this warning.
Warning 1 There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "System.Data.SQLite", "AMD64". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project. ChromeData
There is this error
SQLite error (5): database is locked
I tried closing the browser, but still there is this error. However, when I created a copy of History file and renamed it, gave its path instead of History, the program was working and it could read the file and fetch the data.
I am unable to figure it out where the error is. So, please help. I am posting my 3 class files.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data.SQLite;
using System.Data;
namespace ChromeData
{
class GoogleChrome
{
public List<URL> Urls = new List<URL>();
public IEnumerable<URL> GetHistory()
{
string DocumentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
//Console.WriteLine(DocumentsFolder);
string[] tempstr = DocumentsFolder.Split('\\');
foreach(string s in tempstr)
{
Console.WriteLine(s);
}
string tempstr1 = "";
DocumentsFolder += "\\Google\\Chrome\\User Data\\Default";
if(tempstr[tempstr.Length-1] != "Local")
{
for(int i =0; i<tempstr.Length-1;i++)
{
tempstr1 += tempstr[i] + "\\";
}
DocumentsFolder = tempstr1 + "Local\\Google\\Chrome\\User Data\\Default";
}
Console.WriteLine(DocumentsFolder);
if(Directory.Exists(DocumentsFolder))
{
return ExtractUserHistory(DocumentsFolder);
}
return null;
}
public IEnumerable<URL> ExtractUserHistory(string folder)
{
DataTable HistoryData = ExtractFromTable("urls", folder);
foreach(DataRow row in HistoryData.Rows)
{
string url = row["url"].ToString();
string title = row["title"].ToString();
URL u = new URL(url.Replace('\'',' '), title.Replace('\'',' '), "Google Chrome");
Urls.Add(u);
}
return Urls;
}
DataTable ExtractFromTable(string table, string folder)
{
SQLiteConnection sql_con;
SQLiteDataAdapter DB;
SQLiteCommand sql_cmd;
string dbpath = folder + "\\History";
DataTable DT = new DataTable();
if(File.Exists(dbpath))
{
try
{
sql_con = new SQLiteConnection("Data Source=" + dbpath + ";Version=3;New=False;Compress=True;");
sql_con.Open();
sql_cmd = sql_con.CreateCommand();
string CommandText = "select * from " + table;
DB = new SQLiteDataAdapter(CommandText, sql_con);
DB.Fill(DT);
sql_con.Close();
}
catch(Exception e)
{
TextWriter errorWriter = Console.Error;
errorWriter.WriteLine(e.Message);
}
}
return DT;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ChromeData
{
class TestClass
{
public static List<URL> Urls = new List<URL>();
public static void Main()
{
string path = #"C:\Users\Public\Desktop\history.txt";
GoogleChrome g = new GoogleChrome();
Urls = (List<URL>)g.GetHistory();
using(StreamWriter sw = File.CreateText(path))
{
foreach(URL u in Urls)
{
sw.WriteLine(u.url);
}
}
Console.ReadLine();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChromeData
{
class URL
{
public string url;
public string title;
public string browser;
public URL(string url,string title,string browser)
{
this.browser = browser;
this.title = title;
this.url = url;
}
}
One solution is to copy the file to a temporary location and read it from there.
string source = #"C:\Users\{USERNAME}\AppData\Local\Google\Chrome\User Data\Default\History";
string target = #"C:\Temp\History";
if (File.Exists(target))
{
File.Delete(target);
}
File.Copy(source, target);
string cs = #"Data Source=" + target;
string sql = "Select * From urls";
using (SQLiteConnection c = new SQLiteConnection(cs))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine(rdr[1].ToString());
}
}
}
}
I've found chrome.exe will continue running, and holding the lock, despite exiting the browser as normal.
taskkill.exe /IM chrome.exe /F
This will shut down Chrome, with an added bonus of having a 'restore tabs' button upon restart by the user. Restore tabs is available because you killed forcefully.
In a page when we will click the component Presentation tab we can see the component and template listed there.On clicking of Insert button just below that, it will open another window "Insert component presentation" there also we will have Insert and close button.So now what i need to do While inserting i need to check whether the combination of selected Component and Template is already present there on page or not. If yes then it should prevent inserting the same with a popup like "this combination is already present, select other componet".
Any idea how can i proceed. How can i trigger a Javascript on the Insert button?
EDIT:
When i am subscrbing it to Page i am getting erro.My code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using Tridion.ContentManager.Extensibility.Events;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.ContentManagement;
using System.IO;
using System.Windows.Forms;
namespace MyEventHandlers
{
[TcmExtension("MyEventHandlerExtension")]
public class MyEventHandler : TcmExtension
{
public MyEventHandler()
{
Subscribe();
}
public void Subscribe()
{
EventSystem.Subscribe<Page, SaveEventArgs>(SaveBtnInitiated, EventPhases.Initiated);
}
private void SaveBtnInitiated(Page subject, SaveEventArgs args, EventPhases phase)
{
try
{
List<string> allcplist = new List<string>();
List<string> allcplist = new List<string>();
foreach (ComponentPresentation cp in subject.ComponentPresentations)
{
allcplist.Add(cp.Component.Id + "," + cp.ComponentTemplate.Id);
}
List<string> uniquecplist = allcplist.Distinct().ToList();
if (allcplist.Count != uniquecplist.Count)
{
subject.Checkin(false);
throw new Exception("Page has duplicate component presentation");
}
catch(Exception)
{
}
}
You can implement this in an event handler that is subscribed to the Page Save event and the Initiated phase. When there is a duplicate Component Presentation you can cancel the Save by throwing an exception. The message will be shown in the Message Center in the TCM Explorer.
Why are you subscribing to the Component? I think it should be the Page. Then you can walk through the ComponentPresentations property.
Code to go through the Component Presentations and throw an exception when duplicate presentations are found:
foreach (var cpA in subject.ComponentPresentations)
{
if (subject.ComponentPresentations.Where(cpB => ComponentPresentationsAreEqual(cpA, cpB)).ToList().Count() > 2)
{
throw new DuplicateComponentPresentationsEmbeddedOnPageException();
}
}
And the function to include cpB in the list when it is equal to cpA:
function ComponentPresentationsAreEqual(ComponentPresentation cpA, ComponentPresentation cpB)
{
return cpA.Component.Id == cpB.Component.Id && cpA.ComponentTemplate.Id == cpB.ComponentTemplate.Id;
}
I got my Result with this code Thanks to #Arjen Stobbe
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using Tridion.ContentManager.Extensibility.Events;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.ContentManagement;
using System.IO;
using System.Windows.Forms;
namespace MyEventHandlers
{
[TcmExtension("MyEventHandlerExtension")]
public class MyEventHandler : TcmExtension
{
public MyEventHandler()
{
Subscribe();
}
public void Subscribe()
{
EventSystem.Subscribe<Page, SaveEventArgs>(SaveBtnInitiated, EventPhases.Initiated);
}
private void SaveBtnInitiated(Page subject, SaveEventArgs args, EventPhases phase)
{
try
{
List<string> allcplist = new List<string>();
List<string> allcplist = new List<string>();
foreach (ComponentPresentation cp in subject.ComponentPresentations)
{
allcplist.Add(cp.Component.Id + "," + cp.ComponentTemplate.Id);
}
List<string> uniquecplist = allcplist.Distinct().ToList();
if (allcplist.Count != uniquecplist.Count)
{
subject.Save(false);
throw new Exception("Page has duplicate component presentation");
}
catch(Exception)
{
}
}
But i am not deleting the duplicate CP present on the page. Do i need to add,
for each()
inside
if (allcplist.Count != uniquecplist.Count)
{
}