Thursday, November 22, 2012

Simple MVVM MessageBox Alert

I am fairly new to the MVVM design pattern, but I thought I’d give it a shot for one of my current projects. However, I was baffled to realize there’s no straightforward way to show our coveted MessageBox alert from the ViewModel where all the logic is housed.

I did come across some examples of how to accomplish it but none were satisfactorily easy. I could probably have dissected them enough to figure it out, but creating interfaces or custom UserControls seemed overkill. I just want to use a MessageBox! But I want to do it from the View rather than the ViewModel in order to keep with the design pattern.

Here is a solution I didn’t see anywhere. I may have missed it, and in that case here is another example.

I used my base project code from HERE (The non-refactored original is HERE ). Special thanks to JR and Sean Feldman for the simple MVVM base code.

PROBLEM

The basic premise of MVVM is that the View controls all aspects of the presentation. This includes alerts or other various MessageBox-style popups. Somehow the ViewModel that controls business logic needs to inform the View that an alert should be popped up with certain data.

SOLUTION

To start, we create a class that will encapsulate all our Alert settings. This will include fields for Alert Message, Caption, type of button options, and finally an Action command to execute if the message response is affirmative.

    public class AlertSettings
    {
        public enum AlertType
        {
            YesNo,
            OkCancel,
            OkOnly
        }

        public string DialogMessage { get; private set; }
        public string HeaderText { get; private set; }
        public AlertType Alert_Type { get; private set; }

        private Action commandAction;
        private ICommand command;
        public ICommand CommandToExecute
        {
            get
            {
                if (command == null)
                {
                    command = new Command(commandAction);
                }
                return command;
            }
            private set
            {
                command = value;
            }
        }

        public AlertSettings(string dialogMessage, 
                             string headerText, 
                             AlertType alertType, 
                             Action delegateMethodToExecute)
        {
            this.DialogMessage = dialogMessage;
            this.HeaderText = headerText;
            this.Alert_Type = alertType;
            this.commandAction = delegateMethodToExecute;
        }
    }



Next we will wire up the View to hold a generic FrameworkElement for use as a listener object. This object will be notified of an incoming Alert request using its Tag to hold the Alert settings.

        private FrameworkElement alertListener;

        public InvoiceView()
        {
            InitializeComponent();

            alertListener = ConstructAlertListener();

            this.AddLogicalChild(alertListener);
        }

        /// 
        /// Creates the generic alert object with proper databinding on the Tag     property.
        /// NotifyOnTargetUpdated is used to trigger the alert display
        /// 
        /// 
        private FrameworkElement ConstructAlertListener()
        {
            // This for binding to the ViewModel on an AlertSettings object using
            //  INotifyPropertyChanged to trigger the update on the View
            Binding tagBinding = new Binding();
            tagBinding.Path = new PropertyPath("AlertSettings");
            tagBinding.Mode = BindingMode.OneWay;
            tagBinding.NotifyOnTargetUpdated = true;

            FrameworkElement element = new FrameworkElement();
            element.Visibility = Visibility.Hidden;
            element.SetBinding(TagProperty, tagBinding);
            element.TargetUpdated += alertListener_TargetUpdated;

            return element;
        }

        /// 
        /// Event handler for executing the alert message
        /// 
        /// 
        /// 
        private void alertListener_TargetUpdated(object sender, 
                                                 DataTransferEventArgs e)
        {
            if (alertListener.Tag != null)
            {
                ShowAlert();
            }
        }
The ShowAlert() method that is called in the TargetUpdated event handler will execute the actual showing of the Alert message in whatever way the View is designed to do. In this case, I’m just using our handy MessageBox.

        ///         /// Executes the alert using the settings saved in the alert object Tag property
        ///         private void ShowAlert()
        {
            if (alertListener.Tag == null)
            {
                return;
            }

            if (alertListener.Tag is AlertSettings)
            {
                AlertSettings settings = (AlertSettings)alertListener.Tag;
                ShowAlertByAlertType(settings);
            }
        }

        ///         /// Shows an alert based on alert settings.  This implementation uses MessageBox, but other
        /// implementations can use whatever is desired using the alert settings specified.
        ///         /// AlertSettings object to be used to form an alert message
        private void ShowAlertByAlertType(AlertSettings settings)
        {
            switch (settings.Alert_Type)
            {
                case AlertSettings.AlertType.OkOnly:
                    MessageBox.Show(settings.DialogMessage,
                                    settings.HeaderText,
                                    System.Windows.MessageBoxButton.OK);
                    break;

                case AlertSettings.AlertType.OkCancel:
                    if (MessageBox.Show(settings.DialogMessage,
                                        settings.HeaderText,
                                        MessageBoxButton.OKCancel)
                        == MessageBoxResult.OK)
                    {
                        settings.CommandToExecute.Execute(null);
                    }
                    break;

                case AlertSettings.AlertType.YesNo:
                    if (MessageBox.Show(settings.DialogMessage,
                                        settings.HeaderText,
                                        MessageBoxButton.YesNo)
                        == MessageBoxResult.Yes)
                    {
                        settings.CommandToExecute.Execute(null);
                    }
                    break;

                default:
                    break;
            }
        }
Last of all, we trigger the data in the ViewModel. This is simply done by creating an Alert settings property that will trigger the OnPropertyChanged action, then setting this property with a new instantiation of the settings class whenever an alert is desired.
    ///     /// This was created to set the alert data and then trigger to View using INotifyPropertyChanged
    ///     private AlertSettings alertSettings;
    public AlertSettings AlertSettings
    {
        get { return alertSettings; }
        set
        {
            alertSettings = value;
            OnPropertyChanged(PropertyOf.Resolve(x => x.AlertSettings));
        }
    }

    private void VerifyInvoiceCreationAction()
    {
        DisplayMessage = string.Format("Thanks for creating invoice: {0} {1}", Invoice.Id, Invoice.Receiver);
    }
The alert is triggered using this code:
      string alertMessage = string.Format("Are you sure you want to create invoice {0}?", Invoice.Id);
      AlertSettings = new AlertSettings(alertMessage, "Verify", AlertSettings.AlertType.YesNo, VerifyInvoiceCreationAction);

I’m interested to see if anyone has seen this approach before or can see any major flaws in the logic. Basically, I’m using a generic FrameworkElement Tag property and the FrameworkElement TargetUpdated event handler as a point of entry that triggers a specified action. It seems pretty straightforward.

Here is the full project: MvvmSimple2.zip

Enjoy!

Tuesday, July 13, 2010

What's the big deal with Cloud Security?

Okay, for quite a while I’ve wondered what the big deal was about cloud security. The “Cloud” is a buzz word nowadays that, to me, seemed like nothing more than that. As time has progressed over the past year or so, the buzz word isn’t going away. Microsoft is pouring over Azure, VMware, Google… it seems like most large vendors see the cloud as the future. But, the big hurdle most businesses seem to be stuck on is the idea of “cloud security.”

So I think to myself, “What the heck is that anyway?” What makes cloud security any different than regular security?

On a journey that is still incomplete, I decided to investigate. In my mind, I would say the security of my data in the cloud means I don’t have control over it anymore and it scares me. Could it really be that simple? If so, I would guess the marketing big shots would have evangelized their pants off because there is big money to be had, and it would have been all over by now. But we still see hesitancy in businesses to adopt wholeheartedly.

What else is going on? Let’s take a hospital for example, privately owned. The IT department is sold on the increased processing power, cost savings, etc. and decides to put all their customer data in the cloud. Suddenly questions that didn’t matter before begin to emerge. Who exactly has access to these records? They say it’s encrypted, but what encryption? Whose encryption? How do we know someone hasn’t figured out how to decrypt my data? Traffic is now tunneled over the public network, what kind of measures are in place to prevent sniffing these transmissions?

The questions keep coming. What about government regulations? How do I KNOW that someone working for the cloud company doesn’t have a backdoor admin credential? Can I be liable if we lose records or the data is compromised through a vendor threat?

Other things come into consideration that may not have been worried about before. When something is deleted, how do I know it is ACTUALLY deleted? How many backups are out there that I don’t know about?

After asking these questions, whether you are comfortable or not with the vendor’s answers, does the cost savings really matter? If we keep the data in house, we’ll be paying overhead for maintenance and hardware for a data center of our own, but who cares about that if we have control over our own security? It’s about risk management, a concept CIOs and CFOs know very well but may be missing from eager IT staffers with an eye for the next greatest thing.

I’m not against the cloud, though I gotta say I am getting sick of it because I feel barraged by it. But honestly, with virtualization being an enormous hit for businesses, maybe the cloud really IS the future. So how do we answer the questions if we were the cloud vendor?

First off, I would probably try to integrate existing security technologies into a cloud environment. Having clients use certificates may be a bit much since (I think) they would have to sign each file stored in the cloud. Or just encrypt the whole thing with BitLocker or some other low level encryption tool. I could provide VPN access to a dedicated RRAS server, or utilize RPC over HTTPS technology for each client to protect transmission. Audits will need to be done on file access routinely to prove to clients their data is not compromised. Backup routines and replication topologies will have to be disclosed too.

Regardless, I would also HAVE TO protect myself as the vendor. If maintenance was neglected by the client, it must not be blamed on me. I guess risk management works both ways.

Who knows if these existing security technologies will be enough working together in a cloud environment? Maybe we need an entirely new security scheme. Maybe the cloud technology that’s out there isn’t built on security and needs to be revised from the ground up. If the cloud really is the future, security needs to play a primary role. At least that much is certain.



(Some content references the July 2010 issue of Redmond Mag in an article entitled Cloud Visibility by Jeffrey Schwartz. Just giving credit where it is due.)

Friday, June 4, 2010

Ethical Hacking

Ethical hacking has been more of a hobby of mine for a while, but I'm finding it more and more interesting lately.  My current position in my company is more of a system administrator role than a security role, but thankfully I am allowed some liberty on projects I want to do.  In the future I would like to do some projects with security emphasis, but I haven't decided what yet or what would best support the company.


Anyway, since I am still learning the ins and outs of ethical hacking, I will try to post what I am learning at the moment for other newbies out there.


Remember:  Hacking is not a right, it is a privilege.  Ethical hacking is using your fu to HELP and not HURT.  Use the information I provide with care, and only for good

Friday, May 14, 2010

Populate InfoPath 2010 drop down list through code


In developing forms in InfoPath 2010, I found it quite difficult to manipulate form objects using custom code.  It seems that the form objects are proprietary InfoPath objects and not Windows Forms objects, so you won't be able to use standard techniques to populate the objects, even though they look identical.

In this example, we want to populate a drop down list with data in a database.


Before you pound your head against your desk trying to get this to work (as I did...), there is no way to add the data directly to the drop down list.  Therefore, we must trick the list into using values we pick, and it must do it at runtime.  So, we set up a repeating table that we CAN write to.

First, create a new section.  We will make the whole section invisible so it is not displayed on the published report.



Now give the section a name.  I'm calling it "invisible."



Inside the new section, insert a repeating table.  When it asks, you only need one field.



Give the field in the table a name.  I'm calling it "dropDownOptions."



As long as we are still in setup mode, let's force this invisible section to always be hidden.  This is done by adding a new Formatting rule to the section, select "Hide this control," and set the condition to "The expression", "1=1."



Now that we have a field that will act as our data source, we map the value/display values for the drop down list to this text box.  Right-click on the drop down list and choose Properties to set the data mapping.



Now that the form is set up, let's write the code to populate the table from the database.

Select "Loading Event" from the Developer tab.  (If you don't see the Developer tab, it can be added by going to File, Options, Customize Ribbon, and check the Developer box on the right hand side.)


This will bring up the Code Editor.  I prefer C#, so my code is written in C#.  If you are currently in VB and want to follow this tutorial, close the Code Editor, select "Language" (as shown on the above screen shot), delete the code and then select C# in the drop down list.  Open the Code Editor to continue.

Add the Reference to "System.Data" under References in the Project Explorer (right-hand side of code editor).  Then add the following code to the top of the code screen.

          using System.Data;
             using System.Data.SqlClient;

Under the "// Write code here" section, enter the following code.  Replace database connection as appropriate for your database environment.

            XPathNavigator DOM = this.MainDataSource.CreateNavigator();

            SqlConnection connection = new SqlConnection("Server=[server];Database=[database];UID=[username];PWD=[password];");
            SqlCommand command;
            SqlDataAdapter adapter;
            DataSet dataset;

            try
            {
                // Set up SQL connection and query
                connection.Open();

                command = new SqlCommand();
                command.Connection = connection;
                command.CommandType = CommandType.Text;
                command.CommandText = "SELECT * FROM [table];";

                dataset = new DataSet();                 
                adapter = new SqlDataAdapter(command);
                adapter.Fill(dataset);
 
                // Check dataset
                if (dataset.Tables[0].Rows[0][0].ToString() == null || dataset.Tables[0].Rows[0][0].ToString() == "")
                {
                    throw new Exception("No data found.");
                }
 
                XPathNavigator node = DOM.SelectSingleNode("/my:myFields/my:invisible/my:group2", this.NamespaceManager);
                
                string ns = node.NamespaceURI;
 
                // Fill options
                foreach (DataRow row in dataset.Tables[0].Rows)
                {
                    using (XmlWriter writer = node.AppendChild())
                    {
                        writer.WriteStartElement("group3", ns);
                        writer.WriteElementString("dropDownOptions", ns, row["[column]"].ToString().Trim());
                        writer.WriteEndElement();
                        writer.Close();
                    }
                }
            }
            catch (Exception ex)
            {
            }
            
             if (connection != null)
                connection.Close(); 
 
Anywhere you see the [...] tags, enter data appropriate to your environment. 
 
The last step is to give your form full trust.  This allows the custom code to connect to data outside the form itself.  Go to File,  Form Options, then select "Security and Trust" from the category list, uncheck the option for "Automatically determine security level (recommended)," and choose "Full Trust" from the list.  Click OK.
 
 
 
That's it!  Try running the form and see your drop down options populated!