Friday, February 18, 2011

Web Performance Tests - Context Parameters and Dynamically generated ASP.NET mangled IDs

The application that I was coding tests for, uses dynamically generated names for all the form post parameters.
For e.g. in case of the following line of code
request6Body.FormPostParameters.Add("_hdn_ctl00_ContentPageTabSectionPlaceHolder_WebPartManager1_wp680433384_wp384219079_CompanyAdditionalInfo_FormView_CompanyAdditionalInfo_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted"
 , this.Context["$HIDDEN1._hdn_ctl00_ContentPageTabSectionPlaceHolder_WebPartManager1_wp680433384_wp384219079_CompanyAdditionalInfo_FormView_CompanyAdditionalInfo_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted"].ToString());
the, _WebPartManager1_wp680433384_wp384219079_ will change to _WebPartManager1_wp101957077_wp105468996_ or to something unpredictable on different deployments.

This occurs for about 40~50 form post parameters. However, the rest of the part of the hidden parameters is constant.
I came across a lot of articles posted related to debugging a web test that were focused on how to extract hidden fields that are not getting extracted by the web performance test recorder. In my case, the hidden fields were getting extracted just fine, but a certain portion of the names are getting mangled (perhaps due to ASP.NET and dynamic field generation).

Finally after some effort, I came up with the following workaround

1.       Record the test using the Web Test Recorder and promote the dynamic parameters in it using Visual Studio.
clip_image002[5]
Identify the container controls on the page using the IE Developer toolbar. On the Company page there were three container controls for the page sections (formlets). And, the input controls were concatenated using $ instead of an _ as in the case of the hidden fields.
2.       In the preceding request, add an extraction rule (Extract regular expression) to identify the container controls and stored them in separate context variables.
3.       Perform a search and replace across all the requests
4.       At this point, the problem is that the form post parameters would be something like
                Name: _hdn_{{AdditionalInfoFormlet}}_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted
Value: {{$HIDDEN1._hdn_{{AdditionalInfoFormlet}}_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted}clip_image004[5]
                The context parameter value within another context parameter will cause problems during the test execution from a web test (performance web test).
5.       Now, generate a coded test from this performance web test.
The code generated will be like
request6Body.FormPostParameters.Add(("_hdn_"
                            + (this.Context["AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitte" +
                                "d")), (this.Context["$HIDDEN1._hdn_{{AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitte" +
                    "d}}"));
6.       Search and replace for the context parameters within the context parameters to correct them
request6Body.FormPostParameters.Add(("_hdn_"+ (this.Context["AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted")),
                                                (this.Context["$HIDDEN1._hdn_"+ this.Context["AdditionalInfoFormlet"].ToString() + "_fiscalmonth_ForeignGroup_fgnGrpHelper_MonthFiscalYearEndSearch_selectionCommitted"]).ToString());

7.       The regular expression extract rule was something like this in the generated code
ExtractRegularExpression extractionRule5 = new ExtractRegularExpression();
extractionRule5.RegularExpression = "ctl00_ContentPageTabSectionPlaceHolder_WebPartManager1_.*?_CompanyAdditionalInfo_" +
"FormView_CompanyAdditionalInfo";
extractionRule5.IgnoreCase = false;
extractionRule5.Required = true;
extractionRule5.Index = 0;
extractionRule5.HtmlDecode = true;
extractionRule5.ContextParameterName = "AdditionalInfoFormlet";
request5.ExtractValues += new EventHandler<ExtractionEventArgs>(extractionRule5.Extract);

ExtractRegularExpression extractionRule8 = new ExtractRegularExpression();
extractionRule8.RegularExpression = "ctl00\\$ContentPageTabSectionPlaceHolder\\$WebPartManager1\\$.*?\\$CompanyAdditionalI" +
"nfo\\$FormView_CompanyAdditionalInfo\\$";
extractionRule8.IgnoreCase = false;
extractionRule8.Required = true;
extractionRule8.Index = 0;
extractionRule8.HtmlDecode = true;
extractionRule8.ContextParameterName = "AdditionalInfoInput";

No comments: