Merge pull request #3373 from marek-safar/net-4.6.2
[mono.git] / mcs / class / referencesource / System.Web / Handlers / TraceHandler.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="TraceHandler.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 /*
8  * Trace Handler
9  *
10  * Copyright (c) 1998-1999, Microsoft Corporation
11  *
12  */
13 namespace System.Web.Handlers {
14     using System;
15     using System.Collections;
16     using System.Web;
17     using System.Globalization;
18     using System.Web.Configuration;
19     using System.Web.Hosting;
20     using System.Web.UI;
21     using System.Web.UI.WebControls;
22     using System.Web.UI.HtmlControls;
23     using System.Web.Util;
24     using System.Web.SessionState;
25     using System.Data;
26     using System.Text;
27     using System.Drawing;
28     using System.Security.Permissions;
29
30     /// <devdoc>
31     ///    <para>[To be supplied.]</para>
32     /// </devdoc>
33     public class TraceHandler : IHttpHandler {
34         private const string _style =
35         "<style type=\"text/css\">\r\n" +
36         "span.tracecontent b { color:white }\r\n" +
37         "span.tracecontent { background-color:white; color:black;font: 10pt verdana, arial; }\r\n" +
38         "span.tracecontent table { clear:left; font: 10pt verdana, arial; cellspacing:0; cellpadding:0; margin-bottom:25}\r\n" +
39         "span.tracecontent tr.subhead { background-color:#cccccc;}\r\n" +
40         "span.tracecontent th { padding:0,3,0,3 }\r\n" +
41         "span.tracecontent th.alt { background-color:black; color:white; padding:3,3,2,3; }\r\n" +
42         "span.tracecontent td { color: black; padding:0,3,0,3; text-align: left }\r\n" +
43         "span.tracecontent td.err { color: red; }\r\n" +
44         "span.tracecontent tr.alt { background-color:#eeeeee }\r\n" +
45         "span.tracecontent h1 { font: 24pt verdana, arial; margin:0,0,0,0}\r\n" +
46         "span.tracecontent h2 { font: 18pt verdana, arial; margin:0,0,0,0}\r\n" +
47         "span.tracecontent h3 { font: 12pt verdana, arial; margin:0,0,0,0}\r\n" +
48         "span.tracecontent th a { color:darkblue; font: 8pt verdana, arial; }\r\n" +
49         "span.tracecontent a { color:darkblue;text-decoration:none }\r\n" +
50         "span.tracecontent a:hover { color:darkblue;text-decoration:underline; }\r\n" +
51         "span.tracecontent div.outer { width:90%; margin:15,15,15,15}\r\n" +
52         "span.tracecontent table.viewmenu td { background-color:#006699; color:white; padding:0,5,0,5; }\r\n" +
53         "span.tracecontent table.viewmenu td.end { padding:0,0,0,0; }\r\n" +
54         "span.tracecontent table.viewmenu a {color:white; font: 8pt verdana, arial; }\r\n" +
55         "span.tracecontent table.viewmenu a:hover {color:white; font: 8pt verdana, arial; }\r\n" +
56         "span.tracecontent a.tinylink {color:darkblue; background-color:black; font: 8pt verdana, arial;text-decoration:underline;}\r\n" +
57         "span.tracecontent a.link {color:darkblue; text-decoration:underline;}\r\n" +
58         "span.tracecontent div.buffer {padding-top:7; padding-bottom:17;}\r\n" +
59         "span.tracecontent .small { font: 8pt verdana, arial }\r\n" +
60         "span.tracecontent table td { padding-right:20 }\r\n" +
61         "span.tracecontent table td.nopad { padding-right:5 }\r\n" +
62         "</style>\r\n";
63
64         private HttpContext     _context;
65         private HttpResponse    _response;
66         private HttpRequest     _request;
67         private HtmlTextWriter  _writer;
68
69         [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
70         public TraceHandler() {
71         }
72
73         // IHttpMethods exposed to derived classes
74
75         protected void ProcessRequest(HttpContext context) {
76             ((IHttpHandler)this).ProcessRequest(context);
77         }
78
79         protected bool IsReusable {
80             get {
81                 return ((IHttpHandler)this).IsReusable;
82             }
83         }
84
85         void IHttpHandler.ProcessRequest(HttpContext context) {
86             // VSWhidbey 448844: Disable handler if retail is set to true
87             if (DeploymentSection.RetailInternal ||
88                 (!context.Request.IsLocal && HttpRuntime.Profile.LocalOnly)) {
89                 HttpException e = new HttpException(403, null);
90                 e.SetFormatter(new TraceHandlerErrorFormatter(!DeploymentSection.RetailInternal));
91                 throw e;
92             }
93
94             _context = context;
95             _response = _context.Response;
96             _request = _context.Request;
97             _writer = Page.CreateHtmlTextWriterInternal(_response.Output, _request);
98
99             // if we're in integrated mode, we need to set the content type explicitly
100             if (context.WorkerRequest is IIS7WorkerRequest) {
101                 _response.ContentType = _request.Browser.PreferredRenderingMime;
102             }
103
104             if (_writer == null) {
105                 // Can't create a writer, horked at this point, just return
106                 return;
107             }
108
109             _context.Trace.IsEnabled = false;
110
111             // Validate the input to prevent XSS attacks.
112             _request.ValidateInput();
113
114             _writer.Write("<html>\r\n");
115             _writer.Write("<head>\r\n");
116             _writer.Write(StyleSheet);
117             _writer.Write("</head>\r\n");
118
119             _writer.Write("<body>\r\n");
120             _writer.Write("<span class=\"tracecontent\">\r\n");
121
122             if (!HttpRuntime.Profile.IsConfigEnabled) {
123                 HttpException e = new HttpException();
124                 e.SetFormatter(new TraceHandlerErrorFormatter(false));
125                 throw e;
126             }
127
128             IList datasets = HttpRuntime.Profile.GetData();
129
130             // first check if we should clear data
131             if (_request.QueryString["clear"] != null) {
132                 HttpRuntime.Profile.Reset();
133                 string url = _request.RawUrl;
134                 _response.Redirect(url.Substring(0, url.IndexOf("?", StringComparison.Ordinal)));
135             }
136
137             // then check if we are drilling down
138             string strid = _request.QueryString["id"];
139             if (strid != null) {
140                 int index = Int32.Parse(strid, CultureInfo.InvariantCulture);
141                 if (index >=0 && index < datasets.Count) {
142                     ShowDetails((DataSet) datasets[index]);
143                     ShowVersionDetails();
144                     _writer.Write("</span>\r\n</body>\r\n</html>\r\n");
145                     return;
146                 }
147             }
148
149             // if we get here, its just generic request
150             ShowRequests(datasets);
151             ShowVersionDetails();
152             _writer.Write("</span>\r\n</body>\r\n</html>\r\n");
153         }
154
155         bool IHttpHandler.IsReusable {
156             get { return false; }
157         }
158
159         protected void ShowDetails(DataSet data) {
160             if (data == null) return;
161
162             Table table;
163
164             _writer.Write("<h1>" + SR.GetString(SR.Trace_Request_Details) + "</h1><br>");
165
166             table = CreateDetailsTable(data.Tables[SR.Trace_Request]);
167             if (table != null)
168                 table.RenderControl(_writer);
169
170             table = CreateTraceTable(data.Tables[SR.Trace_Trace_Information]);
171             if (table != null)
172                 table.RenderControl(_writer);
173
174             table = CreateControlTable(data.Tables[SR.Trace_Control_Tree]);
175             if (table != null)
176                 table.RenderControl(_writer);
177
178             table = CreateTable(data.Tables[SR.Trace_Session_State], true /*encodeSpaces*/);
179             if (table != null)
180                 table.RenderControl(_writer);
181
182             table = CreateTable(data.Tables[SR.Trace_Application_State], true /*encodeSpaces*/);
183             if (table != null)
184                 table.RenderControl(_writer);
185
186             table = CreateTable(data.Tables[SR.Trace_Request_Cookies_Collection], true /*encodeSpaces*/);
187             if (table != null)
188                 table.RenderControl(_writer);
189
190             table = CreateTable(data.Tables[SR.Trace_Response_Cookies_Collection], true /*encodeSpaces*/);
191             if (table != null)
192                 table.RenderControl(_writer);
193
194             table = CreateTable(data.Tables[SR.Trace_Headers_Collection], true /*encodeSpaces*/);
195             if (table != null)
196                 table.RenderControl(_writer);
197
198             table = CreateTable(data.Tables[SR.Trace_Form_Collection]);
199             if (table != null)
200                 table.RenderControl(_writer);
201
202             table = CreateTable(data.Tables[SR.Trace_Querystring_Collection]);
203             if (table != null)
204                 table.RenderControl(_writer);
205
206             table = CreateTable(data.Tables[SR.Trace_Server_Variables], true /*encodeSpaces*/);
207             if (table != null)
208                 table.RenderControl(_writer);
209
210         }
211
212         protected void ShowVersionDetails() {
213             _writer.Write("<hr width=100% size=1 color=silver>\r\n\r\n");
214             _writer.Write(SR.GetString(SR.Error_Formatter_CLR_Build) + VersionInfo.ClrVersion +
215                           SR.GetString(SR.Error_Formatter_ASPNET_Build) + VersionInfo.EngineVersion + "\r\n\r\n");
216             _writer.Write("</font>\r\n\r\n");
217         }
218
219         protected void ShowRequests(IList data) {
220             // add the title, application name, physical path, etc.
221             Table table = new Table();
222             table.CellPadding = 0;
223             table.CellSpacing = 0;
224             table.Width = Unit.Percentage(100);
225             TableRow trow = AddRow(table);
226
227             TableCell tcell;
228             AddCell(trow, SR.GetString(SR.Trace_Application_Trace));
229
230             string vroot = _request.ApplicationPath;
231             int vrootLen = vroot.Length;
232
233             trow = AddRow(table);
234             AddCell(trow, "<h2>" + HttpUtility.HtmlEncode(vroot.Substring(1)) + "<h2><p>");
235
236             trow = AddRow(table);
237             AddCell(trow, "[ <a href=\"Trace.axd?clear=1\" class=\"link\">" + SR.GetString(SR.Trace_Clear_Current) + "</a> ]");
238
239             // check if we have permission to show the physical path.  If not, don't show anything.
240             string physicalPath = "&nbsp";
241             if (HttpRuntime.HasAppPathDiscoveryPermission())
242                 physicalPath  = SR.GetString(SR.Trace_Physical_Directory) + _request.PhysicalApplicationPath;
243             trow = AddRow(table);
244             tcell = AddCell(trow, physicalPath);
245
246             table.RenderControl(_writer);
247
248             //////// add the table of requests  ///////
249             table = new Table();
250             table.CellPadding = 0;
251             table.CellSpacing = 0;
252             table.Width = Unit.Percentage(100);
253
254             trow = AddRow(table);
255
256             // title for the table
257             tcell = AddHeaderCell(trow, "<h3><b>" + SR.GetString(SR.Trace_Requests_This) + "</b></h3>");
258             tcell.ColumnSpan = 5;
259             tcell.CssClass = "alt";
260             tcell.HorizontalAlign = HorizontalAlign.Left;
261
262             tcell = AddHeaderCell(trow, SR.GetString(SR.Trace_Remaining) + " " + HttpRuntime.Profile.RequestsRemaining.ToString(NumberFormatInfo.InvariantInfo));
263             tcell.CssClass = "alt";
264             tcell.HorizontalAlign = HorizontalAlign.Right;
265
266
267             // add headers for the columns
268             trow = AddRow(table);
269             trow.HorizontalAlign = HorizontalAlign.Left;
270             trow.CssClass = "subhead";
271             AddHeaderCell(trow, SR.GetString(SR.Trace_No));
272             AddHeaderCell(trow, SR.GetString(SR.Trace_Time_of_Request));
273             AddHeaderCell(trow, SR.GetString(SR.Trace_File));
274             AddHeaderCell(trow, SR.GetString(SR.Trace_Status_Code));
275             AddHeaderCell(trow, SR.GetString(SR.Trace_Verb));
276             AddHeaderCell(trow, "&nbsp");
277
278             // now fill the table with requests
279             bool isAlt = true;
280             for (int i = 0; i < data.Count; i++) {
281                 // for each request
282                 DataSet current = (DataSet)data[i];
283                 trow = AddRow(table);
284                 if (isAlt)
285                     trow.CssClass = "alt";
286
287                 AddCell(trow, (i + 1).ToString(NumberFormatInfo.InvariantInfo));
288                 AddCell(trow, (string) current.Tables[SR.Trace_Request].Rows[0][SR.Trace_Time_of_Request]);
289                 AddCell(trow, HttpUtility.HtmlEncode((string) current.Tables[SR.Trace_Request].Rows[0][SR.Trace_Url]).Substring(vrootLen));
290                 AddCell(trow, current.Tables[SR.Trace_Request].Rows[0][SR.Trace_Status_Code].ToString());
291                 AddCell(trow, (string) current.Tables[SR.Trace_Request].Rows[0][SR.Trace_Request_Type]);
292
293                 TableCell linkcell = AddCell(trow, String.Empty);
294                 HtmlAnchor a = new HtmlAnchor();
295                 a.HRef = "Trace.axd?id=" + i;
296                 a.InnerHtml = "<nobr>" + SR.GetString(SR.Trace_View_Details);
297                 a.Attributes["class"] = "link";
298                 linkcell.Controls.Add(a);
299
300                 isAlt = !isAlt;
301             }
302             table.RenderControl(_writer);
303         }
304
305         ////// Static methods for creating tables //////////
306         static private TableRow AddRow(Table t) {
307             TableRow trow = new TableRow();
308             t.Rows.Add(trow);
309             return trow;
310         }
311
312         static private TableCell AddHeaderCell(TableRow trow, string text) {
313             TableHeaderCell tcell = new TableHeaderCell();
314             tcell.Text = text;
315             trow.Cells.Add(tcell);
316             return tcell;
317         }
318
319         static private TableCell AddCell(TableRow trow, string text) {
320             TableCell tcell = new TableCell();
321             tcell.Text = text;
322             trow.Cells.Add(tcell);
323             return tcell;
324         }
325
326         static internal string StyleSheet {
327             get { return _style;}
328         }
329
330         static internal Table CreateControlTable(DataTable datatable) {
331             Table table = new Table();
332             if (datatable == null) return table;
333
334             TableRow trow;
335             TableCell       tcell;
336             IEnumerator     en;
337             string          parent;
338             string          control;
339             Hashtable       indentLevels = new Hashtable();
340             int             indent;
341             bool            isAlt = false;
342
343             table.Width = Unit.Percentage(100);
344             table.CellPadding = 0;
345             table.CellSpacing = 0;
346
347
348             // add a title for the table - same as table name
349             trow = AddRow(table);
350             tcell = AddHeaderCell(trow, "<h3><b>" + SR.GetString(datatable.TableName) + "</b></h3>");
351             tcell.CssClass = "alt";
352             tcell.ColumnSpan = 5;
353             tcell.HorizontalAlign = HorizontalAlign.Left;
354
355             // add the header information
356             trow = AddRow(table);
357             trow.CssClass = "subhead";
358             trow.HorizontalAlign = HorizontalAlign.Left;
359             AddHeaderCell(trow, SR.GetString(SR.Trace_Control_Id));
360             AddHeaderCell(trow, SR.GetString(SR.Trace_Type));
361             AddHeaderCell(trow, SR.GetString(SR.Trace_Render_Size_children));
362             AddHeaderCell(trow, SR.GetString(SR.Trace_Viewstate_Size_Nochildren));
363             AddHeaderCell(trow, SR.GetString(SR.Trace_Controlstate_Size_Nochildren));
364
365             // prime the indentLevels hashtable with an initial value
366             indentLevels["ROOT"] = 0;
367
368             // now show the tree
369             en = datatable.Rows.GetEnumerator();
370             while (en.MoveNext()) {
371                 // DevDivBugs 173345: Error when enabling trace in an ASPX page
372                 // We also need to HtmlEncode parentId, as we HtmlEncode the controlId.
373                 parent = HttpUtility.HtmlEncode ((string) ((DataRow) en.Current)[SR.Trace_Parent_Id]);
374                 control = HttpUtility.HtmlEncode((string) ((DataRow) en.Current)[SR.Trace_Control_Id]);
375
376                 // this lets us determine how far to indent each control
377                 indent = (int) indentLevels[parent];
378                 indentLevels[control] = indent + 1;
379
380                 // do the indent
381                 StringBuilder indentedControl = new StringBuilder();
382
383                 // Don't want the ID's to break across lines
384                 indentedControl.Append("<nobr>");
385                 for (int i=0; i<indent; i++)
386                     indentedControl.Append("&nbsp;&nbsp;&nbsp;&nbsp;");
387
388                 // page has a blank ID, so we'll fill in something nice for it
389                 if (control.Length == 0)
390                     indentedControl.Append(SR.GetString(SR.Trace_Page));
391                 else
392                     indentedControl.Append(control);
393
394                 trow = AddRow(table);
395                 AddCell(trow, indentedControl.ToString());
396                 AddCell(trow, (string) ((DataRow) en.Current)[SR.Trace_Type]);
397
398                 object size = ((DataRow) en.Current)[SR.Trace_Render_Size];
399                 if (size != null)
400                     AddCell(trow, ((int) size).ToString(NumberFormatInfo.InvariantInfo));
401                 else
402                     AddCell(trow, "---");
403
404                 size = ((DataRow) en.Current)[SR.Trace_Viewstate_Size];
405                 if (size != null)
406                     AddCell(trow, ((int) size).ToString(NumberFormatInfo.InvariantInfo));
407                 else
408                     AddCell(trow, "---");
409
410                 size = ((DataRow) en.Current)[SR.Trace_Controlstate_Size];
411                 if (size != null)
412                     AddCell(trow, ((int) size).ToString(NumberFormatInfo.InvariantInfo));
413                 else
414                     AddCell(trow, "---");
415
416                 // alternate colors
417                 if (isAlt)
418                     trow.CssClass = "alt";
419                 isAlt = !isAlt;
420             }
421
422             return table;
423         }
424
425         static internal Table CreateTraceTable(DataTable datatable) {
426             Table table = new Table();
427             table.Width = Unit.Percentage(100);
428             table.CellPadding = 0;
429             table.CellSpacing = 0;
430
431             if (datatable == null) return table;
432
433             IEnumerator en;
434             bool isAlt = false;
435             TableRow trow;
436             TableCell tcell;
437             DataRow datarow;
438
439             // add a title for the table - same as table name
440             trow = AddRow(table);
441             tcell = AddHeaderCell(trow, "<h3><b>" + SR.GetString(datatable.TableName) + "</b></h3>");
442             tcell.CssClass = "alt";
443             tcell.ColumnSpan = 10;
444             tcell.HorizontalAlign = HorizontalAlign.Left;
445
446             // add the header information - same as column names
447             trow = AddRow(table);
448             trow.CssClass = "subhead";
449             trow.HorizontalAlign = HorizontalAlign.Left;
450             AddHeaderCell(trow, SR.GetString(SR.Trace_Category));
451             AddHeaderCell(trow, SR.GetString(SR.Trace_Message));
452             AddHeaderCell(trow, SR.GetString(SR.Trace_From_First));
453             AddHeaderCell(trow, SR.GetString(SR.Trace_From_Last));
454
455             // now fill in the values, but don't display null values
456             en = datatable.DefaultView.GetEnumerator();
457             while (en.MoveNext()) {
458                 trow = AddRow(table);
459                 datarow = ((DataRowView) en.Current).Row;
460
461                 bool isErr = datarow[SR.Trace_Warning].Equals("yes");
462
463                 // FormatPlainTextAsHtml the values first
464                 tcell = AddCell(trow, HttpUtility.FormatPlainTextAsHtml((string) datarow[SR.Trace_Category]));
465                 if (isErr) tcell.CssClass = "err";
466
467                 StringBuilder message = new StringBuilder(HttpUtility.FormatPlainTextAsHtml((string) datarow[SR.Trace_Message]));
468
469                 object errormessage = datarow["ErrorInfoMessage"];
470                 object errorstack =   datarow["ErrorInfoStack"];
471                 if (!(errormessage is System.DBNull))
472                     message.Append("<br>" + HttpUtility.FormatPlainTextAsHtml((string) errormessage));
473                 if (!(errorstack is System.DBNull))
474                     message.Append("<br>" + HttpUtility.FormatPlainTextAsHtml((string) errorstack));
475
476                 tcell = AddCell(trow, message.ToString());
477                 if (isErr) tcell.CssClass = "err";
478
479                 tcell = AddCell(trow, FormatPotentialDouble(datarow[SR.Trace_From_First]));
480                 if (isErr) tcell.CssClass = "err";
481
482                 tcell = AddCell(trow, FormatPotentialDouble(datarow[SR.Trace_From_Last]));
483                 if (isErr) tcell.CssClass = "err";
484
485
486                 // alternate colors
487                 if (isAlt)
488                     trow.CssClass = "alt";
489
490                 isAlt = !isAlt;
491             }
492
493             return table;
494         }
495
496         private static string FormatPotentialDouble(object o) {
497             // pretty-prints double values (no scientific notation)
498             return (o is double) ? ((double)o).ToString("F6", CultureInfo.CurrentCulture) : o.ToString();
499         }
500
501         static internal Table CreateTable(DataTable datatable) {
502             return CreateTable(datatable, false);
503         }
504
505         static internal Table CreateTable(DataTable datatable, bool encodeSpaces) {
506             Table table = new Table();
507             table.Width = Unit.Percentage(100);
508             table.CellPadding = 0;
509             table.CellSpacing = 0;
510
511             if (datatable == null) return table;
512
513             IEnumerator en;
514             bool isAlt = false;
515             Object[] cells;
516             TableRow trow;
517             TableCell tcell;
518
519             // add a title for the table - same as table name
520             trow = AddRow(table);
521             tcell = AddHeaderCell(trow, "<h3><b>" + SR.GetString(datatable.TableName) + "</b></h3>");
522             tcell.CssClass = "alt";
523             tcell.ColumnSpan = 10;
524             tcell.HorizontalAlign = HorizontalAlign.Left;
525
526             // add the header information - same as column names
527             trow = AddRow(table);
528             trow.CssClass = "subhead";
529             trow.HorizontalAlign = HorizontalAlign.Left;
530             en = datatable.Columns.GetEnumerator();
531             while (en.MoveNext())
532                 AddHeaderCell(trow, SR.GetString(((DataColumn) en.Current).ColumnName));
533
534             // now fill in the values, but don't display null values
535             en = datatable.Rows.GetEnumerator();
536             while (en.MoveNext()) {
537                 cells = ((DataRow) en.Current).ItemArray;
538                 trow = AddRow(table);
539
540                 for (int i=0; i<cells.Length; i++) {
541                     string temp;
542                     if(encodeSpaces)
543                         temp = HttpUtility.FormatPlainTextSpacesAsHtml(HttpUtility.HtmlEncode(cells[i].ToString()));
544                     else
545                         temp = HttpUtility.HtmlEncode(cells[i].ToString());
546
547                     AddCell(trow, (temp.Length != 0) ? temp : "&nbsp;");
548                 }
549
550                 // alternate colors
551                 if (isAlt)
552                     trow.CssClass = "alt";
553                 isAlt = !isAlt;
554             }
555
556             return table;
557         }
558
559         static internal Table CreateDetailsTable(DataTable datatable) {
560             Table table = new Table();
561             table.Width = Unit.Percentage(100);
562             table.CellPadding = 0;
563             table.CellSpacing = 0;
564
565             if (datatable == null) return table;
566
567             TableRow trow = AddRow(table);
568             TableCell tcell = AddHeaderCell(trow, "<h3><b>" + SR.GetString(SR.Trace_Request_Details) + "</b></h3>");
569             tcell.ColumnSpan = 10;
570             tcell.CssClass = "alt";
571             tcell.HorizontalAlign = HorizontalAlign.Left;
572
573             trow = AddRow(table);
574             trow.HorizontalAlign = HorizontalAlign.Left;
575             AddHeaderCell(trow, SR.GetString(SR.Trace_Session_Id) + ":");
576             AddCell(trow, HttpUtility.HtmlEncode(datatable.Rows[0][SR.Trace_Session_Id].ToString()));
577             AddHeaderCell(trow, SR.GetString(SR.Trace_Request_Type) + ":");
578             AddCell(trow, datatable.Rows[0][SR.Trace_Request_Type].ToString());
579
580             trow = AddRow(table);
581             trow.HorizontalAlign = HorizontalAlign.Left;
582             AddHeaderCell(trow, SR.GetString(SR.Trace_Time_of_Request) + ":");
583             AddCell(trow, datatable.Rows[0][SR.Trace_Time_of_Request].ToString());
584             AddHeaderCell(trow, SR.GetString(SR.Trace_Status_Code) + ":");
585             AddCell(trow, datatable.Rows[0][SR.Trace_Status_Code].ToString());
586
587             trow = AddRow(table);
588             trow.HorizontalAlign = HorizontalAlign.Left;
589             AddHeaderCell(trow, SR.GetString(SR.Trace_Request_Encoding) + ":");
590             AddCell(trow, datatable.Rows[0][SR.Trace_Request_Encoding].ToString());
591             AddHeaderCell(trow, SR.GetString(SR.Trace_Response_Encoding) + ":");
592             AddCell(trow, datatable.Rows[0][SR.Trace_Response_Encoding].ToString());
593
594             return table;
595         }
596
597     }
598 }