diff --git a/BinaryMessageFiddlerExtension/BinaryRequestInspector.cs b/BinaryMessageFiddlerExtension/BinaryRequestInspector.cs index 06c1bd0..3f72a3a 100644 --- a/BinaryMessageFiddlerExtension/BinaryRequestInspector.cs +++ b/BinaryMessageFiddlerExtension/BinaryRequestInspector.cs @@ -102,6 +102,14 @@ public override int GetOrder() return 1; } + public override void AssignSession(Session oS) + { + if (viewControl != null && oS != null) + viewControl.DefaultSaveFileName = String.Format("request{0}.xml", oS.id); + + base.AssignSession(oS); + } + public bool bDirty { get; set; } public bool bReadOnly @@ -130,6 +138,9 @@ public byte[] body { // when fiddler updates this inspector's content, our controls' content binaryContent = value; + if (viewControl != null && String.IsNullOrEmpty(viewControl.DefaultSaveFileName)) + viewControl.DefaultSaveFileName = "request.xml"; + UpdateControlContent(); } } diff --git a/BinaryMessageFiddlerExtension/BinaryResponseInspector.cs b/BinaryMessageFiddlerExtension/BinaryResponseInspector.cs index db2dfc8..65207fe 100644 --- a/BinaryMessageFiddlerExtension/BinaryResponseInspector.cs +++ b/BinaryMessageFiddlerExtension/BinaryResponseInspector.cs @@ -57,6 +57,14 @@ public override int GetOrder() return 1; } + public override void AssignSession(Session oS) + { + if (viewControl != null && oS != null) + viewControl.DefaultSaveFileName = String.Format("response{0}.xml", oS.id); + + base.AssignSession(oS); + } + public bool bDirty { get { return false; } @@ -80,6 +88,9 @@ public byte[] body { // when fiddler updates this inspector's content, our control's content binaryContent = value; + if (viewControl != null && String.IsNullOrEmpty(viewControl.DefaultSaveFileName)) + viewControl.DefaultSaveFileName = "response.xml"; + UpdateControlContent(); } } diff --git a/BinaryMessageFiddlerExtension/XmlTreeView.cs b/BinaryMessageFiddlerExtension/XmlTreeView.cs index ab1ff02..bb2ff86 100644 --- a/BinaryMessageFiddlerExtension/XmlTreeView.cs +++ b/BinaryMessageFiddlerExtension/XmlTreeView.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Xml; +using System.IO; namespace BinaryMessageFiddlerExtension { @@ -17,6 +18,8 @@ public partial class XmlTreeView : UserControl // if the message body has fewer than this number of nodes, expand the entire body subtree. private const int AutoExpandAllThreshold = 50; //entirely arbitrary. + public string DefaultSaveFileName { get; set; } + public TreeView TreeView { get @@ -38,10 +41,12 @@ private void BuildContextMenu() // NodeMouseClick doesn't fire for middle click, so emulate that using mouseup/mousedown TreeView.MouseUp += new MouseEventHandler(TreeView_MouseUp); TreeView.MouseDown += new MouseEventHandler(TreeView_MouseDown); + TreeView.KeyDown += new KeyEventHandler(TreeView_KeyDown); TreeView.ContextMenu.MenuItems.Add(new MenuItem("Expand All", ExpandAll_Click, Shortcut.AltRightArrow)); TreeView.ContextMenu.MenuItems.Add(new MenuItem("Collapse All", CollapseAll_Click, Shortcut.AltLeftArrow)); TreeView.ContextMenu.MenuItems.Add(new MenuItem("Copy", CopyMenuItem_Click, Shortcut.CtrlC)); TreeView.ContextMenu.MenuItems.Add(new MenuItem("Copy Tree", CopyTreeMenuItem_Click, Shortcut.CtrlShiftC)); + TreeView.ContextMenu.MenuItems.Add(new MenuItem("Save Tree...", SaveTreeMenuItem_Click, Shortcut.CtrlS)); } public void LoadXml(XmlDocument doc) @@ -207,6 +212,42 @@ private void CopySubtreeContentToClipboard() System.Windows.Forms.Clipboard.SetText(subtreeContent); } + private void SaveSubtreeContentToFile() + { + if (TreeView.SelectedNode == null) + return; + + String subtreeContent = GenerateSubtreeString(TreeView.SelectedNode); + if (subtreeContent == null) + return; + + using (SaveFileDialog saveFileDialog = new SaveFileDialog()) + { + saveFileDialog.AddExtension = true; + saveFileDialog.DefaultExt = "xml"; + saveFileDialog.FileName = String.IsNullOrEmpty(DefaultSaveFileName) ? "decoded-wcf.xml" : DefaultSaveFileName; + saveFileDialog.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*"; + saveFileDialog.OverwritePrompt = true; + saveFileDialog.Title = "Save decoded WCF XML"; + + if (saveFileDialog.ShowDialog(this) != DialogResult.OK) + return; + + try + { + File.WriteAllText(saveFileDialog.FileName, subtreeContent, Encoding.UTF8); + } + catch (Exception ex) + { + MessageBox.Show(this, + "Unable to save decoded XML: " + ex.Message, + "Save decoded WCF XML", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + } + } + private string GenerateSubtreeString(TreeNode treeNode) { XmlNode xml = treeNode.Tag as XmlNode; @@ -264,6 +305,16 @@ private void TreeView_MouseUp(object sender, MouseEventArgs e) } } + private void TreeView_KeyDown(object sender, KeyEventArgs e) + { + if (e.Control && !e.Shift && e.KeyCode == Keys.S) + { + SaveSubtreeContentToFile(); + e.SuppressKeyPress = true; + e.Handled = true; + } + } + private void CopyMenuItem_Click(Object sender, System.EventArgs e) { CopySelectedNodeContentToClipboard(); @@ -274,6 +325,11 @@ private void CopyTreeMenuItem_Click(Object sender, System.EventArgs e) CopySubtreeContentToClipboard(); } + private void SaveTreeMenuItem_Click(Object sender, System.EventArgs e) + { + SaveSubtreeContentToFile(); + } + private void ExpandAll_Click(Object sender, System.EventArgs e) { ExpandAllSelectedNode(); diff --git a/BinaryMessageFiddlerExtension/bin/Release/BinaryMessageFiddlerExtension.dll b/BinaryMessageFiddlerExtension/bin/Release/BinaryMessageFiddlerExtension.dll index 17254ad..2a66f8b 100644 Binary files a/BinaryMessageFiddlerExtension/bin/Release/BinaryMessageFiddlerExtension.dll and b/BinaryMessageFiddlerExtension/bin/Release/BinaryMessageFiddlerExtension.dll differ diff --git a/README.md b/README.md index 34c4bf7..8db44f5 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ The tree view provides the following shortcuts: * Ctrl+c — Copy current node XML * Ctrl+Shift+c — Copy tree XML +* Ctrl+s — Save tree XML to a file * Alt+→ — Expand node and all child nodes * Alt+← — Collapse node and all child nodes * Middle-click — Toggle expand/collapse of node and all child nodes