I have recently updated to Windows 7, VS2010 and IE8. We have an automation suite running tests against IE using WatiN. These tests require the logon dialog handler to be used in order to log different AD Users into the IE Browser.
This works perfectly when using Windows XP and IE8, but now using Windows 7 has resulted in the Windows Security dialog box no longer being recognised, the dialogue box is just being ignored. This is the method being used to startup the browser:
public static Browser StartBrowser(string url, string username, string password)
{
Browser browser = new IE();
WatiN.Core.DialogHandlers.LogonDialogHandler ldh = new WatiN.Core.DialogHandlers.LogonDialogHandler(username, password);
browser.DialogWatcher.Add(ldh);
browser.GoTo(url);
return browser;
}
any suggestions or help would be greatly appreciated...
For whatever reason the code Clint posted had comments instead of entering the username, password and submitting, and referenced an undefined method, but is otherwise OK. Here's some completed (and working) code:
public static Browser Win7Login(string username, string password, string URL) {
Process ieProcess = Process.Start("iexplore.exe", URL);
ieProcess.WaitForInputIdle();
Thread.Sleep(2000);
AutomationElement ieWindow = AutomationElement.FromHandle(ieProcess.MainWindowHandle);
string t = ieWindow.Current.ClassName.ToString();
Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
Condition List_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
Condition Edit_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
Condition button_conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
AutomationElementCollection c = ieWindow.FindAll(TreeScope.Children, conditions);
foreach (AutomationElement child in c) {
if (child.Current.ClassName.ToString() == "#32770") {
// find the list
AutomationElementCollection lists = child.FindAll(TreeScope.Children, List_condition);
// find the buttons
AutomationElementCollection buttons = child.FindAll(TreeScope.Children, button_conditions);
foreach (AutomationElement list in lists) {
if (list.Current.ClassName.ToString() == "UserTile") {
AutomationElementCollection edits = list.FindAll(TreeScope.Children, Edit_condition);
foreach (AutomationElement edit in edits) {
if (edit.Current.Name.Contains("User name")) {
edit.SetFocus();
ValuePattern usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
usernamePattern.SetValue(username);
}
if (edit.Current.Name.Contains("Password")) {
edit.SetFocus();
ValuePattern passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
passwordPattern.SetValue(password);
}
}
}
}
foreach (AutomationElement button in buttons) {
if (button.Current.AutomationId == "SubmitButton") {
InvokePattern submitPattern = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
submitPattern.Invoke();
break;
}
}
}
}
return IE.AttachTo<IE>(Find.By("hwnd", ieWindow.Current.NativeWindowHandle.ToString()), 30);
}
This can also be refactored as a DialogHandler like this:
public class Windows7LogonDialogHandler : BaseDialogHandler
{
private readonly string _username;
private readonly string _password;
AndCondition _conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
readonly AndCondition _listCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
readonly AndCondition _editCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
readonly AndCondition _buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
public Windows7LogonDialogHandler(string username, string password)
{
_username = username;
_password = password;
}
public override bool HandleDialog(Window window)
{
if(CanHandleDialog(window))
{
var win = AutomationElement.FromHandle(window.Hwnd);
var lists = win.FindAll(TreeScope.Children, _listCondition);
var buttons = win.FindAll(TreeScope.Children, _buttonConditions);
var another = (from AutomationElement list in lists
where list.Current.ClassName == "UserTile"
where list.Current.Name == "Use another account"
select list).First();
another.SetFocus();
foreach (var edit in from AutomationElement list in lists
where list.Current.ClassName == "UserTile"
select list.FindAll(TreeScope.Children, _editCondition)
into edits
from AutomationElement edit in edits
select edit)
{
if (edit.Current.Name.Contains("User name"))
{
edit.SetFocus();
var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (usernamePattern != null) usernamePattern.SetValue(_username);
}
if (edit.Current.Name.Contains("Password"))
{
edit.SetFocus();
var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (passwordPattern != null) passwordPattern.SetValue(_password);
}
}
foreach (var submitPattern in from AutomationElement button in buttons
where button.Current.AutomationId == "SubmitButton"
select button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern)
{
submitPattern.Invoke();
break;
}
return true;
}
return false;
}
public override bool CanHandleDialog(Window window)
{
return window.ClassName == "#32770";
}
}
Which is a little bit nicer. You can then use it like this:
using(var ie = new IE())
{
ie.DialogWatcher.Add(new Windows7LogonDialogHandler(#"domain\user", "password"));
ie.GoTo("http://mysecuredwebsite");
}
We have eventually solved this issue by using the Windows Automation 3.0 API to pick up the dialogue box and handle the logging in. This was done as follows:
Fire up an IE process and assign it to an AutomationElement
You now have the ability to traverse through the child elements of the IEFrame, picking up the username and password Edit fields.
Then send the username and password
Once the browser has been authenticated we then attach it to a WatiN IE browser object. The code follows below:
public static Browser LoginToBrowser(string UserName, string Password, string URL)
{
AutomationElement element = StartApplication("IEXPLORE.EXE", URL);
Thread.Sleep(2000);
string t = element.Current.ClassName.ToString();
Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
Condition List_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
Condition Edit_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
Condition button_conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
AutomationElementCollection c = element.FindAll(TreeScope.Children, conditions);
foreach (AutomationElement child in c)
{
if (child.Current.ClassName.ToString() == "#32770")
{
//find the list
AutomationElementCollection lists = child.FindAll(TreeScope.Children, List_condition);
// find the buttons
AutomationElementCollection buttons = child.FindAll(TreeScope.Children, button_conditions);
foreach (AutomationElement list in lists)
{
if (list.Current.ClassName.ToString() == "UserTile")
{
AutomationElementCollection edits = list.FindAll(TreeScope.Children, Edit_condition);
foreach (AutomationElement edit in edits)
{
if (edit.Current.Name.Contains("User name"))
{
edit.SetFocus();
//send the user name
}
if (edit.Current.Name.Contains("Password"))
{
edit.SetFocus();
//send the password
}
}
}
}
foreach (AutomationElement button in buttons)
{
if (button.Current.AutomationId == "SubmitButton")
{
//click the button
break;
}
}
}
}
return IE.AttachToIE(Find.By("hwnd", element.Current.NativeWindowHandle.ToString()), 30) ;
}
We did use a tool called UI Spy to examine the Windows UI. If you run it against XP and Win7 you can clearly see how the structure of the Windows Security dialogue box has changed between the 2 OS's.
Nicholas Riley post works like a charm, however including the using System.Windows.Automation might be a little tricky. I thought microsoft would put this in the GAC, but they do not, at least for me running Windows 7 professional. I even downloaded the Automation Toolkit from here.
Turns out, there is a subject here on stack overflow that shows where the dll's are that you can browse to include as references in your project. The link for that is here.
Essentially, you just need to reference two dll's. UIAutomationClient.dll and UIAutomationTypes.dll (both in the same directory).
Since nobody answered your question, I will, but unfortunately without ready solution.
I don't have Windows 7 to try at this moment, but it seems that WatiN's LogonDialogHandler is not compatible with Windows 7, so you have to write your own DialogHandler. The simplest way is to inherit from BaseDialogHandler. You can look at the source code of existing dialog handlers in WatiN. I made my self very simple and not universal one for handling certificate dialog. WinSpy++ can be very useful during implementation.
If you set whatever process is running your watin to run as administrator in Windows 7, the DialogHandlers work just fine.
I tried to use the two automation examples above and found that they did not handle the scenario when the other credentials have been remembered in which case you only see the password in box. In this case you need to programmatically click the "Use another account" section. So I modified the supplied code to do that and it is now working OK. Here's the modified code:
public static Browser Win7Login(string username, string password, string url)
{
var ieProcess = Process.Start("iexplore.exe", url);
ieProcess.WaitForInputIdle();
Thread.Sleep(2000);
var ieWindow = AutomationElement.FromHandle(ieProcess.MainWindowHandle);
var conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
var listCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
var editCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
var buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
var c = ieWindow.FindAll(TreeScope.Children, conditions);
foreach (AutomationElement child in c)
{
if (child.Current.ClassName == "#32770")
{
// find the list
var lists = child.FindAll(TreeScope.Children, listCondition);
// find the buttons
var buttons = child.FindAll(TreeScope.Children, buttonConditions);
var another = (from AutomationElement list in lists
where list.Current.ClassName == "UserTile"
where list.Current.Name == "Use another account"
select list).First();
another.SetFocus();
foreach (var edit in from AutomationElement list in lists
where list.Current.ClassName == "UserTile"
select list.FindAll(TreeScope.Children, editCondition)
into edits from AutomationElement edit in edits select edit)
{
if (edit.Current.Name.Contains("User name"))
{
edit.SetFocus();
var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (usernamePattern != null) usernamePattern.SetValue(username);
}
if (edit.Current.Name.Contains("Password"))
{
edit.SetFocus();
var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (passwordPattern != null) passwordPattern.SetValue(password);
}
}
foreach (var submitPattern in from AutomationElement button in buttons
where button.Current.AutomationId == "SubmitButton"
select button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern)
{
submitPattern.Invoke();
break;
}
}
}
return IE.AttachTo<IE>(Find.By("hwnd", ieWindow.Current.NativeWindowHandle.ToString()), 30);
}
Thanks to the others who got me most of the way there.
Related
I have a multiple page Web Application that needs to be refreshed after a user has entered in data to then display the data on the table. I have Scoped dependencies so my users do not see the same data table as they are unique to each user. After they enter the data and the page refreshes the page goes blank and the scope is empty. How would I go about keeping the data from the scopes after refresh? I essentially needs a Singlton dependency that isn't shared between users. This is a Blazor Server Side Application. EDIT: Accept Button Method
if (Controlled_Variables.Attendance != null)
{
if (_JBS.CheckFields(_JBF.JobID, _JBF.WorkCenter, _JBF.SetupRun) == false)
{
string prompted = await jsRunTime.InvokeAsync<string>("alert", "Please Verify Job ID, Work Center, and Setup/Run are selected!");
}
else
{
FilledOut = true;
_JBF.transactionData = Guid.NewGuid();
_JBF.jobOperationID = _JBF.WorkCenter;
DateTime recordDate = DateTime.Now;
JobOperationRecord JOR = await _JBS.GetJobOperationRecordByOperationID(_JBF.WorkCenter);
WorkCenterRecord SingleWorkCenter = await _JBS.GetWorkCenterInformation(JOR.Work_Center);
EmployeeRecord Employee = await _JBS.GetEmployeeRecord(Controlled_Variables.Employee_ID);
try
{
if (Check.IsThisAnActiveJob(_JBF.JobID))
{
bool Complete = await First_Article_Complete(_JBF.jobOperationID, _JBF.SetupRun);
if (Complete)
{
Controlled_Variables.Sessions.Clear();
Controlled_Variables.Sessions = await _JBS.GetOpenJobOperationTimeSessionForUser(Controlled_Variables.Employee_ID);
bool activeNonGhostSession = false;
foreach (JobOperationSessionManager Session in Controlled_Variables.Sessions)
{
if (Session.ghost == "Y")
{
Controlled_Variables.ActiveSession = Session;
activeNonGhostSession = true;
}
}
_JBS.UpdateJobOperationStatus(JOR.Job_Operation.ToString(), JOR.Status == "C" ? "C" : "S");
if (!activeNonGhostSession && !_JBF.GhostedCheck)
{
_JBS.AddNewJobOperationTimeSessionForUser(Controlled_Variables.Employee_ID, "N", _JBF.transactionData.ToString(), JOR.Work_Center,
_JBF.jobOperationID, _JBF.JobID, recordDate.ToString("yyyy-MM-dd HH:mm:ss"), _JBF.jobOperationTime.ToString(), _JBF.SetupRun);
_JBF.sessionManagerCreated = true;
_JBS.InsertIntoTransactionDetail_NewEntry_JobOperation(_JBF.transactionData.ToString(), _JBF.jobOperationID, _JBF.jobOperationTime.ToString(),
JOR.Work_Center, _JBF.JobID);
_JBF.transDetailCreated = true;
_JBS.InsertIntoTransactionData_NewEntry_JobOperation(_JBF.transactionData.ToString(), Controlled_Variables.Employee_ID, recordDate.ToString());
_JBF.transDataCreated = true;
_JBS.InsertIntoJobOperationTime_NewEntry_JobOperationStart(_JBF.jobOperationID, Controlled_Variables.Employee_ID, recordDate.ToString(),
Employee.Hourly_Rate.ToString(), SingleWorkCenter.Labor_Burden.ToString(), SingleWorkCenter.Machine_Burden.ToString(), SingleWorkCenter.GA_Burden.ToString(),
_JBF.jobOperationTime.ToString(), JOR.Work_Center, _JBF.jobOperationTimeObjectID.ToString(), JOR.ObjectID.ToString(), Employee.ObjectID.ToString());
_JBF.jobOperationTimeCreated = true;
btnStartJob = true;
btnStopJob = false;
NavManage.NavigateTo(NavManage.Uri, forceLoad: true);
string prompted = await jsRunTime.InvokeAsync<string>("alert", "The job has been entered successfully.", "ERROR");
Sorry for the confusion for the use of refresh. I needed to reload the table to allow the data put in by users to be visable after they hit accept. To do this I added a navigation manager
NavManage.NavigateTo(NavManage.Uri, forceLoad: true);
Which force loads the page and displays the new data. If there may be another way to do this to keep the scope I am open to using a different method. As you can see I have tried to just recall the method in which the table data is loaded into to possibly get the new data populated but then the application never reiterates the loop to actually display the data on the page
#for (int i = 0; i < Controlled_Variables.TransactionData.Count; i++)
{
var TransacData = Controlled_Variables.TransactionData[i];
TransacData.index = i;
#for (int l = 0; l < Controlled_Variables.TransactionDetail.Count; l++)
{
var transacdetail = Controlled_Variables.TransactionDetail[l];
transacdetail.index = l;
TransactionDetailRecord selectData = Controlled_Variables.TransactionDetail[l];
#if (transacdetail.Transaction_Data == TransacData.Transaction_Data)
{
<div><input value="#selectData" type="radio" name="Select" onclick="#(() => ShowSelectedRecord(selectData, TransacData))"> </div>
<div>#transacdetail.Target_Integer</div>
<div>#transacdetail.Job</div>
<div>#Controlled_Variables.Job.Part_Number</div>
<div>#TransacData.Transaction_Start</div>
if (TransacData.Transaction_Type == 10)
{
<div>#TransacData.Transaction_Type</div>
btnStartJob = true;
btnStopJob = false;
}
else
{
<div>#TransacData.Transaction_Type</div>
btnStartJob = false;
btnStopJob = true;
}
<div>#Controlled_Variables.Job.Customer</div>
<div>#transacdetail.Work_Center</div>
<div>#transacdetail.Quantity</div>
<div>#TransacData.Transaction_End</div>
<div>#transacdetail.Entry_Type</div>
<div>#transacdetail.Labor_Hrs</div>
<div>#transacdetail.Machine_Hrs</div>
<div>#TransacData.Transaction_Data</div>
<div>#transacdetail.Transaction_Detail</div>
}
}
}
Given the following formflow setup...
return builder
.Field(new FieldReflector<CarValuationDialog>(nameof(Mileage))
.SetValidate(async (state, value) =>
{
var result = new ValidateResult { IsValid = true };
if (int.TryParse(value.ToString(), out int mileage))
{
state.Mileage = mileage;
result.IsValid = true;
}
else
{
result.Feedback = "That isn't valid number. Can you enter it again please?";
result.IsValid = false;
}
return result;
}))
.Field(new FieldReflector<CarValuationDialog>(nameof(HappyWithAnswersBuying))
.SetActive(carValuationDialog => carValuationDialog.ValuationOption == ValuationOptions.LookingToOwn)
.SetPrompt(CreateHappyWithAnswersBuyingPrompt())
.SetDefine(HappyWithAnswersDefinitionMethod))
.OnCompletion(GetValuationAndDisplaySummaryToUser)
.Build();
I want to try out custom validation on the mileage answer given by the user. The code in SetValidate executes, and given a valid integer, that number is assigned to state.Mileage.
However, when the prompt asking the user if they are happy with the answers is shown, the mileage is still set to 0..
Here is the code for the prompt..
private static PromptAttribute CreateHappyWithAnswersBuyingPrompt()
{
StringBuilder sb = new StringBuilder(100);
sb.Append("Are you happy with your answers? <br /><br />");
sb.Append("{&RegistrationNumber}: {RegistrationNumber} <br />");
sb.Append("{&Mileage}: {Mileage:N0} miles {||}");
return new PromptAttribute(sb.ToString())
{
ChoiceStyle = ChoiceStyleOptions.Buttons,
FieldCase = CaseNormalization.InitialUpper
};
}
Before I added the SetValidate code, the mileage was shown perfectly fine in the prompt. But since I'm now manually setting state.Mileage, it's not being persisted across for some reason.
Man, I seriously need to "check the plug" on my code...
Basically I had not set the Value property of the ValidateResult instance...
.SetValidate(async (state, value) =>
{
var result = new ValidateResult { IsValid = true, Value = value };
....
}
After doing that, the mileage value now appears in the prompt...
I'm updating a pivot viewer application and have run into the following issue. Hopefully someone will have an answer as I'm stuck.
The issue: When the page is loaded the side with properties and other features load fine, but the trading cards don't load any images. Some of them load the default white background while the majority show a dark grey, almost black background. All of them can be zoomed into and show all the properties, but no images.
Debugging: I've discovered that commenting out some of the properties causes the images to load correctly every time. If I comment out only 1 or 2 then the images will load some of the time (about 2 out of 10 page refreshes). Currently there are 29 properties contained in a list and the data is being loaded from a database and then used in the pivotviewer.ItemsSource.
Any ideas?
Code with some name changes (the option two one is the one with the properties I'm commenting out):
MainPage.xaml.cs
public MainPage()
{
InitializeComponent();
PivotViewModel pivotModel = new PivotViewModel();
CollectionsComboBox.SelectedIndex = 0;
this.DataContext = pivotModel;
}
private void DropDown_ItemSelected(object sender, EventArgs e)
{
// Process selected index change here
if (((ComboBox)sender).SelectedValue == "Option One")
{
OptionOnePivotViewModel OptionOnePivot = new OptionOnePivotViewModel();
PivotViewer.ItemsSource = OptionOnePivot.Data;
PivotViewer.PivotProperties = OptionOnePivot.PivotProperties;
PivotViewer.ItemTemplates = OptionOnePivot.TemplateCollection;
PivotViewer.ItemAdornerStyle = blankAdorner;
}
else
{
OptionTwoPivotViewModel OptionTwoPivot = new OptionTwoPivotViewModel();
PivotViewer.ItemsSource = OptionTwoPivot.Data;
PivotViewer.PivotProperties = OptionTwoPivot.PivotProperties;
PivotViewer.ItemAdornerStyle = basicAdorner;
PivotViewer.ItemTemplates = OptionTwoPivot.TemplateCollection;
}
}
OptionTwoPivotViewModel.cs:
public OptionTwoPivotViewModel()
{
DomainContext = new OptionTwoDomainContext();
Data = DomainContext.Load(DomainContext.GetHRDatasQuery()).Entities;
PivotProperties = getPivotProperties();
SmallTemplate = "EmpSmall";
TemplateCollection = new PivotViewerItemTemplateCollection()
{
(PivotViewerItemTemplate) Application.Current.Resources[SmallTemplate]
};
}
private List<PivotViewerProperty> getPivotProperties()
{
List<PivotViewerProperty> properties = new List<PivotViewerProperty>
{
new PivotViewerStringProperty{ Id="Name", Options=PivotViewerPropertyOptions.CanSearchText, DisplayName="Name", Binding=new System.Windows.Data.Binding("Name")},
new PivotViewerStringProperty{ Id="Status", Options=PivotViewerPropertyOptions.CanFilter, DisplayName="Status", Binding=new System.Windows.Data.Binding("Status")},
new PivotViewerDateTimeProperty{ Id="StartDate", Options=PivotViewerPropertyOptions.CanFilter, DisplayName="Start Date", Binding=new System.Windows.Data.Binding("StartDate")},
//additional properties follow...
};
return properties;
Edit: I've noticed that if I set a breakpoint in the following property getter then continue the images also load fine.
public ImageSource BackgroundImage
{
get
{
string location = Image_Location;
location = location.Substring(location.LastIndexOf("/"));
Uri uri;
if (Image_Location.Contains(".gif"))
{
uri = new Uri(Image_Location, UriKind.Absolute);
}
else
{
var host = Application.Current.Host.Source.Host;
uri = new Uri("https://" + host + "/fileLibrary/employees/images/500"+location, UriKind.RelativeOrAbsolute);
}
// set the image source
BitmapImage bmpImg = new BitmapImage(uri);
_loaded = _backgroundImage != null;
if (!_loaded)
{
bmpImg.ImageOpened += ImageOpened;
bmpImg.ImageFailed += ImageFailed;
}
return new BitmapImage(uri);
}
TemplateCollection = new PivotViewerItemTemplateCollection()
{
(PivotViewerItemTemplate) Application.Current.Resources[SmallTemplate]
};
Not assigning a property in the initializer above?
i creat an accounting application in mvc3. i have journal voucher form in it.in this form master and detail data is on single view.i use html table and text boxes in html table for create my grid.I saved my data into sql server 2008 r2 database in 2 tables with help of json and wcf services on single button click.(means on save button click all the master and detail data is inserted in database.there is no edit button on each grid line for editing data into database.
Now I want to perform my form's edit functionality on single button click into database.
for this purpose i have an idea that i use sqltransaction object and delete data from database temporarily and then insert new data into database and then do the sqltran.commit or sqltrans.rollback on sucess/fail base of transaction.
for this purpose i create a function in DAL in which it firstly bind sqltransaction with command and then do delete functionality with dataadapter and stored procedure.
but my stored procedure is not called and data is not delete i monitor it in sql server profiler.
I paste my code here plzzz any one tell me where i do mistake.
public bool JVInsertDAL1(JVEntity Obj, bool FMode, bool EMode, bool DMode)
{
bool FinRes = false;
DataSet ObjDs = new DataSet();
//function call to fill tables scheme in dataset
ObjDs = FillDSDAL(ObjDs, "", "");
if (FMode == false && DMode == true)
{
ObjDs = FillDSDAL(ObjDs, Obj.VNo, Obj.Type);
}
//==============================
///*********MASTER DATA INSERTION************************
if (EMode != true || DMode != false)
{
if (sqlConnection.State == ConnectionState.Closed)
{
sqlConnection.Open();
}
sqlTransaction = sqlConnection.BeginTransaction();
}
try
{
if (FMode == false && DMode == true)
{
SqlCommand cmdDeleteLedg = new SqlCommand("SpGLdelete", sqlConnection, sqlTransaction);
cmdDeleteLedg.CommandType = CommandType.StoredProcedure;
SqlCommand cmdDeleteHead = new SqlCommand("SpGlHeadDelete", sqlConnection, sqlTransaction);
cmdDeleteHead.CommandType = CommandType.StoredProcedure;
cmdDeleteHead.Parameters.Add("#VNo", SqlDbType.Char, 10, "VNo").Value = Obj.VNo;
cmdDeleteHead.Parameters.Add("#Type", SqlDbType.Char, 2, "Type").Value=Obj.Type;
cmdDeleteLedg.Parameters.Add("#VNo", SqlDbType.Char, 10, "VNo").Value = Obj.VNo;
cmdDeleteLedg.Parameters.Add("#Type", SqlDbType.Char, 2, "Type").Value = Obj.Type;
//-----------------PROCEDURE FOR DELETE RECORD DURING EDIT MODE-------------
ObjDadp.DeleteCommand = cmdDeleteLedg;
ObjDadp.Update(ObjDs, "Gledg");
ObjDadp.DeleteCommand = cmdDeleteHead;
ObjDadp.Update(ObjDs, "Glhead");
ObjDs.AcceptChanges();
ObjDs.Clear();
}
if (FMode == true)
{
SqlCommand sqlCommand = new SqlCommand("SPJVHeadInsert", sqlConnection, sqlTransaction);
sqlCommand.CommandType = CommandType.StoredProcedure;
SqlCommand sqlCommand1 = new SqlCommand("SPJVLedgInsert", sqlConnection, sqlTransaction);
sqlCommand1.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add("#Type", SqlDbType.Char, 2, "Type");
sqlCommand.Parameters.Add("#VNo", SqlDbType.Char, 10, "VNo");
sqlCommand.Parameters.Add("#VDate", SqlDbType.DateTime, 10, "VDate");
sqlCommand1.Parameters.Add("#Type", SqlDbType.Char, 2, "Type");
sqlCommand1.Parameters.Add("#VNo", SqlDbType.Char, 10, "VNo");
sqlCommand1.Parameters.Add("#VDate", SqlDbType.DateTime, 10, "VDate");
sqlCommand1.Parameters.Add("#Code", SqlDbType.Char, 10, "Code");
ObjRow = ObjDs.Tables["GlHead"].NewRow();
ObjRow["Type"] = Obj.Type;
ObjRow["VNo"] = Obj.VNo;
ObjRow["VDate"] = Obj.VDate;
ObjRow["RefRemarks"] = Obj.RefRemarks;
ObjDs.Tables["GlHead"].Rows.Add(ObjRow);
foreach (var trans in Obj.GLedg)
{
ObjRow = ObjDs.Tables["Gledg"].NewRow();
ObjRow["Type"] = trans.Type;
ObjRow["VNo"] = trans.VNo;
ObjRow["VDate"] = trans.VDate;
ObjRow["Code"] = trans.Code;
ObjDs.Tables["Gledg"].Rows.Add(ObjRow);
}
//----------------------------------------------------
ObjDadp.InsertCommand = sqlCommand;
ObjDadp.Update(ObjDs, "GlHead");
ObjDadp.InsertCommand = sqlCommand1;
ObjDadp.Update(ObjDs, "GLedg");
//----------------------------------------------------
}//END OF FMODE=TRUE CONDITION
//------------------------------------------------------
//****************************************
if (DMode != true || EMode != true)
// if (EMode != true || DMode != false)
{
sqlTransaction.Commit();
}
//************************************
}//end of try
catch (SqlException sqlError)
{
sqlTransaction.Rollback();
}
catch (Exception ex)
{
sqlTransaction.Rollback();
}
finally
{
if (EMode != true || DMode != true)
{
if (sqlConnection.State == ConnectionState.Open)
{
sqlConnection.Close();
}
}
}
//******end of detail insertion***************************************************
if (FMode == false && DMode == true)
{
if (ObjDs.HasErrors== false)
{
FinRes = true;
}
else
{
FinRes = false;
}
}
if (FMode == true)
{
if (ObjDs.HasErrors == false)
{
FinRes = true;
}
else
{
FinRes = false;
}
}
return FinRes;
}
In above code i pass FMode: true, EMode: false, DMode: false for save data and it insert data into database.
FMode: false, EMode: true, DMode: true when delete data from database in editing mode.
and finally FMode: true, EMode: true, DMode: false for insert data after deletion from database in editing mode.
Any suggestions for solve my problem?
From the code above it seems that you don't change the contents of the tables Glhead and Gledg.
Calling the Update method of the SqlDataAdapter when the rows of the mentioned tables are all in the state DataRowState.Unchanged result in no action on the database.
When an application calls the Update method, the DbDataAdapter
examines the RowState property, and executes the required INSERT,
UPDATE, or DELETE statements iteratively for each row, based on the
order of the indexes configured in the DataSet.
You need to delete the row from the datatable and then call the Update method of the SqlDataAdapter
I have a problem with TreeScope finding an element in Internet Explorer when searching the Name property and ControlType property.
mainElement is the AutomationElement representing "internet Explorer_Server.
all automation elements are listed under mainElement in UISpy.
public Auto.AutomationElement GetElementByNameAndControlType(Auto.AutomationElement mainElement, System.Windows.Automation.ControlType controlType, string propertyName)
{
Auto.AutomationElement target = null;
Auto.PropertyCondition typeCondition1 = new Auto.PropertyCondition (Auto.AutomationElement.ControlTypeProperty, controlType);
Auto.PropertyCondition typeCondition2 = new Auto.PropertyCondition(Auto.AutomationElement.NameProperty, propertyName);
Auto.AndCondition andCondition2 = new Auto.AndCondition(typeCondition1, typeCondition2);
target = mainElement.FindFirst(Auto.TreeScope.Descendants, andCondition2);
return target;
}
I was finally able to find the element with the code below, but really want to understand why the code above didn't work.
public Auto.AutomationElement GetElementByIsValuePatternAvailablePropertyAndName(Auto.AutomationElement mainElement, string name, Auto.ControlType controlType)
{
Auto.AutomationElement target = null;
Auto.Condition conditions = new Auto.AndCondition(new Auto.PropertyCondition(Auto.AutomationElement.IsEnabledProperty, true),
new Auto.PropertyCondition(Auto.AutomationElement.IsValuePatternAvailableProperty, true));
// Find all children that match the specified conditions.
Auto.AutomationElementCollection elementCollection = mainElement.FindAll (Auto.TreeScope.Descendants, conditions);
foreach (Auto.AutomationElement ae in elementCollection)
{
if (ae.Current.Name == name)
{
target = ae;
break;
}
}
return target;
}
Please add assembly references of UIAutomationClient and UIAutomationTypes in your project ;-)
via martin's answer