Index was out of range c# when checking against AD - c#

When checking the user against active directory, I also check their mail attribute try to store it into a session variable
However, when the users AD account doesn't have a mail address, I would like to display this on the screen for them.
At the moment an exception is caught for index out of range
How can I can check for this so that I can set the label property? I obviously want to avoid setting it in the catch.
try
{
var mail = adsSearchResult.Properties["mail"][0] ;
if (mail == null)
{
Label3.Text = "blablabla";
return;
}
else
{
Session["email"] = adsSearchResult.Properties["mail"][0].ToString().ToLower();
}
}
catch (Exception ex)
{
Response.Write(ex);
}

You simply could add null and length check, you should actually if there is such possibility.
try {
if (adsSearchResult.Properties["mail"]!= null && adsSearchResult.Properties["mail"].Any()) {
var mail = adsSearchResult.Properties["mail"][0];
if (mail == null) {
Label3.Text = "blablabla";
return;
} else {
Session["email"] = adsSearchResult.Properties["mail"][0].ToString()
.ToLower();
}
}
} catch (Exception ex) {
Response.Write(ex);
}

Related

Check for appointment items that have been updated after the initial sent invitation

I have an Outlook plugin that is tied to the item send event. When the user clicks send, I get a list of recipients and I check for external addresses.
I need to be able to distinguish Outlook appointment items that have been updated after the original item was sent.
Is there a DASL property, a Redemption property or an standard appointment item property to determine this?
For mailitems, I check the length of the ConversationIndex string , if the length is 44, I know it’s a new message. If greater than 44, I know it’s a reply or forward.
//for example
Outlook.MailItem mailItem = Item as Outlook.MailItem;
string convID = mailItem.ConversationIndex;
if ((convID.Length = 44)) //new messages are always 44
{ //do something }
I’m looking to do a similar check on new appointment items but the conversation index does not increase for appointment items.
This question - link - is similar but not the same because the FInvited DASL property is always true after the item has been sent.
I was able to check the new meeting/appointment items by subscribing to the Outlook.InspectorsEvents_NewInspectorEventHandler event and when this event is fired you can then check the fInvited DASL property. Since this event fires before the ItemSend event, I always know the current item's fInvited value.
Here's an example that I hope helps someone else in the future:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
olInspectors = this.Application.Inspectors;
olInspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Compose_New_Message_Inspector);
}
public bool AppointmentSent { get; set; }
static void Main(string[] args)
{
void Compose_New_Message_Inspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
try
{
var Item = Inspector.CurrentItem;
if (Item is Outlook.MailItem)
{
//not concerned with mail items
}
else if (Item is Outlook.AppointmentItem)
{
// added to check if an appontment is new or if it's beeing updated or has alredy been sent
// fInvited=false if meeting is newly composed and true if it has already been sent
Outlook.AppointmentItem apptItem = Item as Outlook.AppointmentItem;
bool fInvited;
try
{
fInvited = apptItem.PropertyAccessor.
GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/8229000B");
Debug.WriteLine("fInvited =" + fInvited);
AppointmentSent = fInvited;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
try
{
if (apptItem != null)
{
Marshal.ReleaseComObject(apptItem);
}
}
catch (Exception ex)
{
}
}
// To hangle right-click action (Forward Meeting or Foward occurrences)
// fInvited=false if meeting is newly composed and true if it has already been sent
else if (Item is Outlook.MeetingItem)
{
Outlook.MeetingItem meetingItem = Item as Outlook.MeetingItem;
bool fInvited;
try
{
fInvited = meetingItem.PropertyAccessor.
GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/8229000B");
Debug.WriteLine("fInvited =" + fInvited);
AppointmentSent = fInvited;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
try
{
if (meetingItem != null)
{
Marshal.ReleaseComObject(meetingItem);
}
}
catch (Exception ex)
{
}
}
try
{
if (Item != null)
{
Marshal.ReleaseComObject(Item);
}
}
catch (Exception ex)
{
}
}
catch (Exception ex)
{
}
}
}

Splitting data access and catching data to form

In my project I'm trying to write code that will be nice to understand.
I currently split my data access functions in a seperate class.
What I'm trying to achieve however, is to catch the errors back to my form. I am not getting this currently and I was wondering why.
In my form I have the following code:
private void btn_Save_ItemClick(object sender, ItemClickEventArgs e)
{
if (dal.updatePerson(ObjectAfterSaving))
{
MessageBox.Show("Updated!");
}
else
{
MessageBox.Show("error");
};
}
In my dal object (derived from the DataAccess_Person class), I have the following method:
public bool updatePerson(Person p)
{
conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Database"].ConnectionString);
SqlCommand command = new SqlCommand(#"UPDATE Person
SET PersonName = #PersonName
WHERE PersonID = #PersonID", conn);
command.Parameters.Add("#PersonName", SqlDbType.VarChar).Value = p.Name
{
try
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
int a = command.ExecuteNonQuery();
conn.Close();
if (a > 0)
{
return true;
}
else
{
return false;
}
}
catch (SqlException ex)
{
ex.ToString();
return false;
}
}
}
My question is: let's say if my method falls in the catch. Will my front end (form) show it (Sql Exception for example) ? Or will i just get 'error' ? And If I will just get error, how I can improve my code to show the Exception instead of error?
A simple way is to remove the try catch from your DAL and add it to the form. For example:
private void btn_Save_ItemClick(object sender, ItemClickEventArgs e)
{
var result = "Success";
try
{
dal.updatePerson(ObjectAfterSaving);
}
catch (SqlException sqlEx)
{
result = sqlEx.Message;
}
catch (Exception ex)
{
result = ex.Message;
}
MessageBox.Show(result);
}
Just note that there's a lot of ways you can do this. My preference is to not include DAL specific exception types in my UI. Instead I may return a custom result type that has an errorcode and message and let my UI display that or generate a custom message based on the error code.
You‘ll just get „error“ in case of a SqlException. All other exceptions will crash your program if you don‘t have a global exception handler. If you want to show the error message you could introduce an out variable for the error message:
bool successful = MyMethod(out string errorMessage)
if (!successful)
{
MessageBox.Show(errorMessage);
}
public bool MyMethod(out string errorMessage)
{
errorMessage = "";
try
{
// do some stuff
return true;
}
catch(Exception ex)
{
errorMessage = ex.Message;
return false;
}
}

What is the best practice for try catch inside try catch?

My function is saving a customer data when there is a booking request. There are 2 conditions : force to save booking even if customer data is not filled yet or save booking with completed customer data.
I do the try catch and raise the exception to user in case that the program found that this customer doesn't exist to confirm that user wants to create new customer data or not. If yes, open new form and if not, force the program to save.
Inside forcing the program to save, I want to catch other exceptions if exist.
Currently, I'm doing like this.
try
{
booking = new Booking();
booking.RoomID = roomID;
booking.Tel = txtTel.Text;
booking.PersonalID = txtId.Text;
booking.Name = txtBookBy.Text;
booking.CheckinDate = dtpCheckin.Value;
booking.CheckoutDate = dtpCheckin.Value.AddDays(Convert.ToDouble(cbNight.SelectedItem));
mng.SaveBooking(booking, false);
if (MessageBox.Show("Data is saved") == DialogResult.OK)
{
this.Close();
}
}
catch (NewCustomerException ex)
{
DialogResult dialog = MessageBox.Show("Customer doesn't exist in database. Do you want to create new customer?", "Please confirm", MessageBoxButtons.YesNo);
if (dialog == DialogResult.Yes)
{
String param = txtBookBy.Text + "," + txtTel.Text + "," + txtId.Text;
CustomerForm oForm = new CustomerForm(param);
oForm.Show();
}
else if (dialog == DialogResult.No)
{
try
{
mng.SaveBooking(booking, true);
}
catch (Exception ex1)
{
MessageBox.Show(ex1.Message);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
You never use exceptions to control the flow of your program.
The mng.SaveBooking(booking, false); should return true/false to signal the calling code that a customer doesn't exist.
Better to write a method that gives you back just this information and then use that info to write the following code
try
{
// Check if customer already registered
if(mng.CustomerExists(CustomerKey))
{
mng.SaveBooking(booking, false);
if (MessageBox.Show("Data is saved") == DialogResult.OK)
{
this.Close();
}
}
else
{
DialogResult dialog = MessageBox.Show("Customer doesn't exist in database. " +
"Do you want to create new customer?", "Please confirm", MessageBoxButtons.YesNo);
if (dialog == DialogResult.Yes)
{
.....
}
else
{
.....
}
}
}
catch(Exception ex)
{
... somthing unexpected here
}
Make separate try catch block so that every try catch block follow single responsibility. In catch block you can manage the statement for which it throw exception and you can use that manage statement result in the next try catch block.
try {
booking = new Booking();
booking.RoomID = roomID;
booking.Tel = txtTel.Text;
booking.PersonalID = txtId.Text;
booking.Name = txtBookBy.Text;
booking.CheckinDate = dtpCheckin.Value;
booking.CheckoutDate = dtpCheckin.Value.AddDays(Convert.ToDouble(cbNight.SelectedItem));
mng.SaveBooking(booking, false);
if (MessageBox.Show("Data is saved") == DialogResult.OK) {
this.Close();
}
}
catch (NewCustomerException ex) {
DialogResult dialog = MessageBox.Show("Customer doesn't exist in database. Do you want to create new customer?", "Please confirm", MessageBoxButtons.YesNo);
}
if (dialog == DialogResult.Yes) {
String param = txtBookBy.Text + "," + txtTel.Text + "," + txtId.Text;
CustomerForm oForm = new CustomerForm(param);
oForm.Show();
}
else if (dialog == DialogResult.No) {
try {
mng.SaveBooking(booking, true);
}
catch (Exception ex1) {
MessageBox.Show(ex1.Message);
}
}
}

goto in c# and its usage

I have a subroutine. It comapares whether values are empty then doing something. For example, if they are empty, then warnings are raised.
The code works fine. But when value are not empty, the warnings are still pop out. Please help me to correct the logic.
Thanks.
private void btnNew_Click(object sender, EventArgs e)
{
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
goto Msg1;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
goto Msg2;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
goto Msg3;
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
Msg1:
MessageBox.Show("Description is required.");
Msg2:
MessageBox.Show("Abbr is required.");
Msg3:
MessageBox.Show("Please select another one, this one is already used.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
From the above code, you see. if txtbox1 has some value, the program still displays Msg1. I want to avoid it.
Because labels are just labels, and code after them is executed sequentially.
Why can't you do just this:
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
return;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
return;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
MessageBox.Show("Please select another one, this one is already used.");
return;
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
It's so much more readable.
Restructure your code to avoid goto - it is a relic and not much use in a properly object oriented codebase.
Returning from the method, throwing exceptions or building an errors dictionary are all better options than using goto.
For example, you can have a List<string> errors which you add to when you get an error condition.
If it is empty, no errors were encountered, if it isn't, there were.
This is a good case were goto is the wrong way to go. Use something like this instead.
private void btnNew_Click(object sender, EventArgs e)
{
try
{
bool error = false;
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
error = true;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
error = true;
}
if (SortOrders.Contains(Convert.ToDecimal(numericOrder.Value)
{
MessageBox.Show("Please select another one, this one is already used.");
error = true;
}
if(error)
return;
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Edit
Just figured that my code didn't actually do the same as his first sample since it only displayed the first error no matter how many that occured. Updated my sample to accomodate for that.
I've always been taught to avoid goto like the plague, and it's something I've followed for years. I've never even considered it to be an option when writing code.
Thinking about it though, I did read an article a few years ago (which I can't find now) which said you could credibly use gotos only if you used it to jump down code, and not up: a rule that is stuck to here.
Check here for more info: Does anyone still use [goto] in C# and if so why?
There are better ways of using goto statement, for instacne using "return" (when used in the middle of a method), "break" and "continue". Have you ever used one of these?
private void btnNew_Click(object sender, EventArgs e)
{
try
{
var description = txtbox1.Text.Trim();
if (string.IsNullOrEmpty(description))
{
MessageBox.Show("Description is required.");
return;
}
var abbr = txtbox2.Text.Trim();
if (string.IsNullOrEmpty(abbr))
{
MessageBox.Show("Abbr is required.");
return;
}
var numericOrderValue = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains(numericOrderValue)
{
MessageBox.Show("Please select another one, this one is already used.");
return;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = description;
dr["Abbr"] = abbr;
dr["SortOrder"] = numericOrderValue;
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnNew_Click(object sender, EventArgs e)
{
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
MessageBox.Show("Please select another one, this one is already used.");
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Try this. It works.

Belgium Identity Card feature crashes on IIS W3WP.exe

My registration tool has a feature which allows candidates to load their personal information (like name, address, ..) from an ID.
When I compile the application with the build-in webserver in VS2010, and press the button to load ID information into textboxes, there is no problem. When I publish it on the localhost (with IIS), it crashes when I press the button.
This is what I received in my event viewer:
0
APPCRASH
Not available
0
w3wp.exe
7.5.7601.17514
4ce7a5f8
KERNELBASE.dll
6.1.7601.17651
4e211319
e0434352
0000b9bc
0
7e796e20-f3e1-11e0-8ea3-60eb69b01829
0
I'm working on a 64-bit laptop, use the Belgium Identity Card SDK.
Here you can find my code for the button;
protected void Button1_Click(object sender, EventArgs e)
{
//READ eID
ClearTextBoxes();
try
{
BEID_ReaderSet ReaderSet;
ReaderSet = BEID_ReaderSet.instance();
BEID_ReaderContext Reader;
Reader = ReaderSet.getReader();
bool bCardPresent = Reader.isCardPresent();
if (Reader.isCardPresent())
{
if (Reader.getCardType() == BEID_CardType.BEID_CARDTYPE_EID
|| Reader.getCardType() == BEID_CardType.BEID_CARDTYPE_FOREIGNER
|| Reader.getCardType() == BEID_CardType.BEID_CARDTYPE_KIDS)
{
try
{
Load_eid(Reader);
}
catch (Exception ex)
{
labelEx.Text = ex.Message;
}
}
else
{
labelEx.Text = "No valid card, please insert a valid IDcard";
}
}
else
{
labelEx.Text = "No IDcard found, please insert your card";
}
BEID_ReaderSet.releaseSDK();
}
catch (BEID_Exception ex)
{
BEID_ReaderSet.releaseSDK();
labelEx.Text = "No valid cardreader found, please connect a valid reader";
}
catch (StackOverflowException ex)
{
BEID_ReaderSet.releaseSDK();
labelEx.Text = "Error: " + ex;
}
catch (OutOfMemoryException ex)
{
BEID_ReaderSet.releaseSDK();
labelEx.Text = "Error: " + ex;
}
}
private void Load_eid(BEID_ReaderContext Reader)
{
try {
BEID_EIDCard card;
card = Reader.getEIDCard();
if (card.isTestCard())
{
card.setAllowTestCard(true);
}
BEID_EId doc;
doc = card.getID();
txtFirstN.Text = doc.getFirstName();
txtLastN.Text = doc.getSurname();
txtDOB.Text = doc.getDateOfBirth();
//CUT GETSTREET IN STREET AND HOUSENO
string street= doc.getStreet();
string[] words = street.Split(' ');
txtStreet.Text = words[0];
txtHouseNo.Text = words[1];
txtPostalCode.Text = doc.getZipCode();
txtCity.Text = doc.getMunicipality();
//sText += "Country = " + doc.getCountry() + "\r\n";
}
catch (Exception ex)
{
BEID_ReaderSet.releaseSDK();
labelEx.Text = "Error: " + ex;
}
}
How can I solve this problem?
Most likely your Application Pool is running under a user which does not have a privilege to access the card reader. This would cause a driver fault which can crash the w3wp.exe process.
Change it to a dedicated user and assign appropriate privileges for this user, or for testing purposes, set it to run under localsys.
Move your code to Javascript (in the browser/html).
I don't think the IIS user has the permission to communicate with the ID reader API.

Categories

Resources