WatiN : Textfields are not getting automated while running the code as - c#

WatiN.Core.IE window = new WatiN.Core.IE();
// Frames
// Model
TextField txt_txtName = window.TextField(Find.ByName("txtName"));
TextField txt_txtPassword = window.TextField(Find.ByName("txtPassword"));
Button btn_btnLogin = window.Button(Find.ByName("btnLogin"));
// Code
window.GoTo("http://134.554.444.55/asdfgfghh/");
txt_txtName.TypeText("fghfjghm");
txt_txtPassword.TypeText("gfhgjfgh");
btn_btnLogin.Click();
}
only the window.GoTo("http://134.554.444.55/asdfgfghh/"); code works and the rest are doing nothing,
When I am using a catch block it throws exception as
Could not find INPUT (hidden) or INPUT (password) or INPUT (text) or INPUT (textarea) or TEXTAREA element tag matching criteria: Attribute 'name' equals 'txtName' at "http://134.554.444.55/asdfgfghh/ (inner exception: Unable to cast COM object of type 'System.__ComObject' to interface type 'mshtml.IHTMLElement'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}' failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).)

My answer is very similar with Pavlo's one, but I must advice to use Page which is a built-in suport for Model as described by Pavlo.
Create a class MyPage
public class MyPage : WatiN.Core.Page
{
public TextField NameField
{
get { return Document.TextField(Find.ByName("txtName")); }
}
public TextField PasswordField
{
get { return Document.TextField(Find.ByName("txtPassword")); }
}
public TextField LoginButton
{
get { return Document.Button(Find.ByName("btnLogin")); }
}
}
Then you can just call .Page<MyClass> method.
using(var browser = new IE("http://134.554.444.55/asdfgfghh/"))
{
var page = browser.Page<MyClass>();
page.NameField.TypeText("name field");
page.PasswordField.TypeText("password field");
page.LoginButton.Click();
}

When you call Button, TextField or whatever it does not create mapping it actually searches for control on page. And if the page is not opened yet than control does not exist.
You can create properties that will find control when you request it. So you define a particular model as class with appropriate properties.
public TextField txt_txtName
{
get
{
return window.TextField(Find.ByName("txtName"));
}
}
Added: If creating properties does not work for you, then use this:
var model = new
{
txt_txtName = new Func<TextField>(() => window.TextField(Find.ByName("txtName"))),
txt_txtPassword = new Func<TextField>(() => window.TextField(Find.ByName("txtPassword"))),
btn_btnLogin = new Func<Button>(() => window.Button(Find.ByName("btnLogin")))
};
window.GoTo("http://134.554.444.55/asdfgfghh/");
model.txt_txtName().TypeText("fghfjghm");
model.txt_txtPassword().TypeText("gfhgjfgh");
model.btn_btnLogin().Click();

Related

How to check if the dynamically created instance of a winform is already open in c#

I know how to check for the form if it is already open. But, I am having a hard time finding the same if the form was created dynamically. How can I find the type of dynamic object? In the code below, I am trying to find what goes in Application.OpenForms.OfType<???>().Any(). I am sure it is something silly but I can't crack it.
public static bool OpenForm(string formName)
{
try
{
string namespace = MethodInfo.GetCurrentMethod().ReflectedType.Namespace;
Assembly assembly = Assembly.GetExecutingAssembly();
var _form = assembly.CreateInstance($"{namespace}.{formName}") as Form;
if (Application.OpenForms.OfType<???>().Any())
{
//Form is already open, do nothing
return true;
}
if (_form != null)
_form.Show();
return true;
}
catch (Exception ex)
{
return false;
}
}
If you mean to use a generic method to verify whether an instance of a Form type exists and, if it's not, then run it, you can use a generic method and to perform both the check and create the instance:
Check whether an instance of the type exists:
Application.OpenForms.OfType<T>()
Create the instance and show the Form if none that type is already created:
public static bool OpenForm<T>() where T : Form, new()
{
if (Application.OpenForms.OfType<T>().Any()) return true;
try {
var f = new T();
f.Show();
return true;
}
catch (Exception) {
return false;
}
}
Since you're passing the name of a Form in your code snippet, you might instead check whether an instance of a Form with that name already exists:
Application.OpenForms.OfType<Form>().Any(f => f.Name.Equals(formName))
If it doesn't, first check whether the assembly actually contains a type with that name (passing true, causes GetType() to throw if it fails to find a match, so it goes to the same exception handler):
var formType = assembly.GetType(formAsmName, true);
Otherwise, it goes on and creates the instance.
Next time you try to create an instance of a Form with that name, the first check will return true and won't create a new instance.
public static bool OpenForm(string formName)
{
if (Application.OpenForms.OfType<Form>().Any(f => f.Name.Equals(formName))) return true;
try {
var assembly = Assembly.GetExecutingAssembly();
var formAsmName = $"{assembly.GetName().Name}.{formName}";
var formType = assembly.GetType(formAsmName, true); // <- Throws
var form = assembly.CreateInstance(formType.FullName) as Form;
form.Show();
return true;
}
catch (Exception) {
// Throw a specific exception instead?
return false;
}
}

How to pass the name of a class as paramenter to a method and instantiate that class inside the method?

I would like to be able to pass a class name as parameter to a method, and then inside that method create an object of that class with certain parameters.
A concrete (simplified) example:
This is a method to compute an OperationResult
private IOperationResult<Unit> GetFailedOperationResult(IEnumerable<StrictSide> sides, IFailedOperationInfo failedOperationResult)
{
var exception = failedOperationResult.Exception.HasValue() ? failedOperationResult.Exception.Value() : null;
if (exception != null)
{
return new FailedResult<Unit>(
new InvalidBundleErrorKeyResolver(new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName, sides), exception)));
}
throw new InvalidOperationException("Failed operation result during bundle consistency check does not contain error or exception.");
}
Depending on the operation that we get the error from, we use different ErrorKeyResolvers. I would like to pass these ErrorKeyResolver as a parameter to the method, so that I don't need to make different GetFailedOperationResult methods for each error type.
Inspired by How to use class name as parameter in C#
I tried something like this:
private IOperationResult<Unit> GetFailedOperationResult(IEnumerable<StrictSide> sides,IFailedOperationInfo failedOperationResult, IErrorResourceKeyResolver resourceKeyResolver)
{
var exception = failedOperationResult.Exception.HasValue() ? failedOperationResult.Exception.Value() : null;
if (exception != null)
{
return new FailedResult<Unit>(Activator.CreateInstance(typeof(resourceKeyResolver),new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName, sides), exception)));
}
throw new InvalidOperationException("Failed operation result during bundle consistency check does not contain error or exception.");
}
But I cannot do typeof(resourceKeyResolver) because I cannot use a variable as a type.
Is there a nice way to do this? Is it even a good thing to do? I also read that dynamics should be avoided so I wonder if saving some code repetition is worth it here.
EDIT: the input parameters should be: private IOperationResult<Unit> GetFailedOperationResult(IEnumerable<StrictSide> sides,IFailedOperationInfo failedOperationResult, string resourceKeyResolver)
And from the class name as string I should be able to find the type.
If you pass the class as interface you can use following code to instantiate resolver
var resolver = Activator.CreateInstance(resourceKeyResolver.GetType(),
new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName,
sides), exception));
Otherwise, if you use the class name (assembly-qualified-name) you can, for example, convert it to type first and call the above line again
var resolverType = Type.GetType(resourceKeyResolverClassName);
var resolver = Activator.CreateInstance(resolverType ,
new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName,
sides), exception));
See here for documentation of GetType() method

"Object reference not set to an instance of an object" on Retrieving data

I have tried to retrieve data from SQL database. I am using Entity Framework core. Its retrieving the required data from the database. I can see the data coming when debugging but the data is not assigning to the variable of type var. FYI, the value of variable type is 0 and its basically an enum, i typecast it to int. Below is the code
public async Task<string> GetMailTemplateByType(Models.TemplateTypes type)
{
var mailTemplate = await _userDbContext.MailTemplates.FirstOrDefaultAsync(mt => mt.TemplateType==((int)type));
return mailTemplate.MailHtml;
}
Here is the definition:
var HtmlTemplate = await _coreDataManager.GetMailTemplateByType(TemplateTypes.Activation);
when debug with try catch, Its showing
Object reference not set to an instance of an object
what is the problem here?
We can see from your code that you recieve the following mail template object:
Id = {aeced541-7003-437e-8f77-4605766fb62c};
MailHtml = "Hi, Thank you so much for signing up.Here is Confirmation link to proceed further ...";
TemplateType = 0;
Here you are passing some TemplateType value we don't know
public async Task<string> GetMailTemplateByType(Models.TemplateTypes type)
{
Here you compare that type value to the TemplateType property in the MailTemplate object we see in the dubugger window
var mailTemplate = await _userDbContext.MailTemplates.FirstOrDefaultAsync(mt => mt.TemplateType==((int)type));
But if type is not 0, it will not return the MailTemplate object as the MailTemplate object we see in the debugger window has a TemplateType value of 0, thus FirstOrDefaultAsync will return a null value, see "fault returns NullReferenceException if no match is found"
public async Task<string> GetMailTemplateByType(Models.TemplateTypes type)
{
var mailTemplate = /*your expression from screenshot*/.FirstOrDefault();
if(mailTemplate = null)
throw new NullReferenceException();
return mailTemplate;
}
..........................
try
{
GetMailTemplateByType(TemplateTypesVariable);
}
catch(NullReferenceException err)
{
Console.WriteLine("template does not exist");
}
It looks like you are trying to receive data which does not exist.
Why do you even select the whole object? ef-core is just like sql, select what you need (in your case just do a
var mailTemplate = await _userDbContext.MailTemplates.Where(mt => mt.TemplateType==((int)type)).Select(x => x.MailHtml).FirstOrDefaultAsync();
but this will still not work, since your entity says that the TemplateType is 0 (and your enum starts with 1). Guessing you saved it wrong
wanted to write this as a comment but i just created this account

Value getting reset between ajax calls in Controller

In my controller, the method that returns the View also initializes a few values for some class-level properties:
private string igc = String.Empty;
private string igcCode = String.Empty;
private bool isSuggested = false;
public ActionResult Codes(Codes objCodes)
{
try
{
FillDropDowns(objCodes);
igc = String.Empty;
if (objICDCodes.FromWhere.IndexOf("MedicalInfo-Suggested") >= 0)
{
igc = objCodes.FromWhere.Remove(0, "MedicalInfo-Suggested-".Length);
igcCode = igc.Substring(0, igc.IndexOf("-")).Trim();
objCodes.ICGCode = igcCode;
isSuggested = true;
}
}
catch (Exception ex)
{
//logging error
ElmahLogUtility.ErrorException(ex);
}
return View(base.GetViewPath("Codes"), objCodes);
}
Additionally, there is this method which gets called to bind data to a grid on the page:
public JsonResult GetSelectedCodesInfo(List<SearchField> searchFields, GridDataSourceRequest request)
{
//creating the instance of DataSourceResult.
DataSourceResult dataSourceResult = null;
try
{
// Creating the instance of CommonBLL to load the values.
CommonBLL objCommonBLL = new CommonBLL();
if (isSuggested)
{
searchFields.Add(new SearchField() { ElementName = "aIGCode", Value = igcCode });
searchFields.Add(new SearchField() { ElementName = "aFor", Value = "EtiologicDiagnosis" });
}
// Getting the Codes information and storing in the DataSource Result.
dataSourceResult = objCommonBLL.GetSelectedCodesInfo(searchFields, request);
}
catch (Exception ex)
{
//Logging the Exception
ElmahLogUtility.ErrorException(ex);
}
// Returning the Result.
return Json(dataSourceResult, JsonRequestBehavior.AllowGet);
}
isSuggested gets set to true when the View is created, but when the data is bound to the grid isSuggested is set to false for some reason.
My grid is defined in a Razor view like so:
#Html.Grid("CodesSelectionGrid").ReadSource("Controller", "GetSelectedCodesInfo").OnGridDataBound("AssignCodeValues").Lazyload(true).EnableGrouping(false).EnableSorting(true).PageSize(10).Height("390px").Width("610px").EnablePaging(true).EnableFiltering(false).EnableMultiSelect(true).SelectionMode(SelectionMode.Single, "GetSelectedCodeDetails").RowSelection(GridRowSelection.None).ShowToolBar(true).SelectionCSSClass("icd-editable-cell").PageButtonCount(3)
That .ReadSource("Controller", "GetSelectedCodesInfo") bit is what refers to the Controller and the method on the controller to call. So, it's calling the second snippet of code above.
I must be accessing two separate instances of my Controller class, but I do not know how to solve this problem. How can I do this? How could I have my grid pass a reference of the Codes object? Then I could just get the values from there for the grid...
This is the expected behavior. isSuggested is a class level variable. Every time you make an Http request, a new instance of your controller will be created. That means the variable will be initialized to false. Remember, Http is Stateless :)
If you want to persist a variable value between multiple http calls, you need to persist it. You have different options like
Persist to a database table and read from that in the second call
Write to a file in disk and read from that in the second call
Save to user session and read from that in the second call

Unable to cast object of type 'ASP.XXX_master' to type 'XXX.MasterPage'

I want to access a specific control in a master page from the page which use it so i write the following code line :
this.Master.FindControl("pnl_Buttonss").Visible = false;
Now
I get the following exception from the page .designer.cs :
Unable to cast object of type 'ASP.masterpage2_master' to type 'GuideUI.MasterPage'.
public new GuideUI.MasterPage Master {
get {
return ((GuideUI.MasterPage)(base.Master));
}
}
this 's the code which throw the exception .How to fix this error
Make sure you have used the same master page on that page as the one you are casting to.

Categories