Another unpleasant thing about WebService

Source: Internet
Author: User
When I was working on the project yesterday, I found another unhumanized place of WebService, which was recorded here, hoping to help students who encountered similar problems. Many large B/S projects are usually divided into several layers. to reproduce the problem, I simplified it to three layers: (below) Code For demonstration purposes only, it may not be of much practical use)

1. Model LayerPlace some entity classes required by the business (these classes are usually required to be serializable to facilitate serialization and transfer in the "service layer" mentioned later). Here, we will demonstrate how, three classes are created:1.1Person class

Using system; namespace model {[serializable] public class person {public person () {} private int _ salary = 1280; // minimum wage in Shanghai // <summary> // income // </Summary> Public int salary {get {return _ salary ;} set {_ salary = value ;}} private string _ name = "No Name "; /// <summary >/// name /// </Summary> Public string name {get {return _ name ;}set {_ name = value ;}} private datetime _ Birthday = new datetime (1900, 1, 1 ); /// <summary> /// birthday // </Summary> Public datetime birthday {get {return _ birthday;} set {_ Birthday = value ;}} public override string tostring () {return string. format ("name = {0}, Birthday = {1}, salary = {2}", this. name, this. birthday, this. salary );}}}
1.2, The personqueryparameters class usually has search requirements for the set of person classes (such as datatable and list <person>), and the search fields must be dynamically changed. For convenience, encapsulate some common search parameters in this class
Using system; using system. collections. generic; using system. LINQ; using system. text; namespace model {[serializable] public class personqueryparameters {public personqueryparameters () {} private int _ salary_min = consts. salarymin; // <summary> // salary range (minimum) /// </Summary> Public int salary_min {get {return _ salary_min ;} set {_ salary_min = value;} private int _ salary_max = consts. salarymax; // <summary> // salary range (maximum) /// </Summary> Public int salary_max {get {return _ salary_max ;} set {_ salary_max = value;} private datetime _ birthday_min = consts. birthdaymin; // <summary> // birthday range (minimum) /// </Summary> Public datetime birthday_min {get {return _ birthday_min ;} set {_ birthday_min = value;} private datetime _ birthday_max = consts. birthdaymax; // <summary> // birthday range (maximum) /// </Summary> Public datetime birthday_max {get {return _ birthday_max ;} set {_ birthday_max = value ;}} public override string tostring () {return string. format ("salary_min = {0}, salary_max = {1}, birthday_min = {2}, birthday_max = {3}", this. salary_min, this. salary_max, this. birthday_min, this. birthday_max );}}}
Note: A consts class is used, which will be mentioned immediately below 1.3, The consts class is only used to define constants for convenience.
 
Using system; namespace model {[serializable] public static class consts {public static readonly datetime birthdaymin = new datetime (1900, 1, 1 ); public static readonly datetime birthdaymax = new datetime (2012, 12, 24); public static readonly int salarymin = 1280; public static readonly int salarymax = 1000000 ;}}
2. WebService Layer The business functions required by other subsystems are made public at this layer in the form of services. We create a query. asmx to provide the "query person" service. (Note: of course, this layer must reference the model layer)
Using system; using system. collections. generic; using system. LINQ; using system. web. services; using model; namespace WebService {// <summary> // summary description for query /// </Summary> [WebService (namespace = "http://yjmyzz.cnblogs.com/")] [webservicebinding (conformsto = wsiprofiles. basicprofile1_1)] [system. componentmodel. toolboxitem (false)] public class query: system. web. services. webService {[Webmethod (description = "query person information")] public list <person> queryperson (personqueryparameters PARS) {// for demonstration purposes, directly construct a list <t> as the search source list <person> lstsrc = new list <person> () {new person () {Birthday = datetime. parse (""), name = "Zhang San", salary = 5000}, new person () {Birthday = datetime. parse ("1985-6-1"), name = "", salary = 10000}, new person () {Birthday = datetime. parse ("1975-12-8"), name = "Wang Wu", salary = 8000} ,}; Ienumerable <person> result = lstsrc. asenumerable (); # region processing search if (pars. birthday_min! = Consts. birthdaymin) {result = result. Where (C => C. Birthday> = pars. birthday_min);} If (pars. birthday_max! = Consts. birthdaymax) {result = result. Where (C => C. Birthday <= pars. birthday_max);} If (pars. salary_min! = Consts. salarymin) {result = result. Where (C => C. salary> = pars. salary_min);} If (pars. salary_max! = Consts. salarymax) {result = result. Where (C => C. Salary <= pars. salary_max) ;}# endregion return result. tolist ();}}}

3. The website (UI) layer is only responsible for UI rendering, business functions are implemented by requesting the WebService layer. After adding a service reference to query. asmx In the WebService layer, we create a default. aspx page to test the queryperson service.

Using system; using website_asmx_no_ref_model.wslayer; using website_asmx_no_ref_model.properties; namespace website_asmx_no_ref_model {public partial class default: system. web. UI. page {protected void page_load (Object sender, eventargs e) {using (query service = new query () {// dynamically set the asmx path service of WebService. url = settings. default. website_asmx_no_ref_model_wslayer_query; personqueryparameters pars = new personqueryparameters (); // query PARs of persons whose salaries are between 3 and 5 K. salary_min= 3000; pars. salary_max = 5000; // pars. birthday_min = datetime. parse ("1979-1-1"); person [] result = service. queryperson (PARs );}}}}
After a bunch of arguments, I finally finished explaining the background. Now the problem is just getting started. From the code at the UI Layer, it seems that everything is perfect. The various entities at the model layer Class Definition After the asmx service is referenced in the UI Layer, it is automatically taken to the UI Layer. If we right-click "personqueryparameters" in the code above and go to the definition, we will see the code automatically generated by vs.net:
/// <Remarks/> [system. codedom. compiler. generatedcodeattribute ("system. XML "," 4.0.30319.225 ")] [system. serializableattribute ()] [system. diagnostics. debuggerstepthroughattribute ()] [system. componentmodel. designercategoryattribute ("Code")] [system. XML. serialization. xmltypeattribute (namespace = "http://yjmyzz.cnblogs.com/")] public partial class personqueryparameters {private int salary_minfield; private int salary_maxfield; private system. datetime birthday_minfield; private system. datetime birthday_maxfield; // <remarks/> Public int salary_min {get {return this. salary_minfield;} set {This. salary_minfield = value ;}/// <remarks/> Public int salary_max {get {return this. salary_maxfield;} set {This. salary_maxfield = value ;}/// <remarks/> public system. datetime birthday_min {get {return this. birthday_minfield;} set {This. birthday_minfield = value ;}/// <remarks/> public system. datetime birthday_max {get {return this. birthday_maxfield;} set {This. birthday_maxfield = value ;}}}
Well, if you can't wait to press F5 to run it, you will find that the code at the UI Layer can never find any person record. The problem is: The personqueryparameters class in the website is no longer the personqueryparameters class in the model layer. Now! (Even if the two "class names" and "Class Attribute Member names" are identical) observe that the personqueryparameters definition in the Model layer is automatically defined for the personqueryparameters generated by vs.net in the website, you will find that the code for assigning initial values to Private Members in the original model layer, such
 
Private int _ salary_min = consts. salarymin;
Already changed
 
Private int salary_minfield;
In other words, the initial attribute assignment is lost! (Or changed) So the if judgment statement of the search part in WebService
 
If (pars. birthday_max! = Consts. birthdaymax)
Should be changed
 
If (pars. birthday_max! = Default (datetime ))
This is a relatively hidden problem. There will be no problems during the compilation period, and no errors will be reported during the runtime. It can only be found at the runtime through the debugging breakpoint. Knowing the problem, Solution There is: Method 1 : The model layer does not assign any initial values to private members for the "search parameter entity class. In this way, the people who write the WebService layer will naturally not think of using if (pars. xxx = consts. XXX) to judge Method 2 : If the model-Layer Code cannot be modified, you can also modify the if statement code in WebService. Considering compatibility
 
If (pars. birthday_max! = Consts. birthdaymax)
This code should become
 
If (! (Pars. birthday_max = consts. birthdaymax | pars. birthday_max = default (datetime )))

Continue nagging: vs.net, such as the "auto-generate asmx industry-specific entity-class definition" code, even after the UI Layer adds the model layer project reference, still this way. However, in subsequent tests, we found that if we replace asmx with WCF (. SVC), after Model Reference is added to the UI Layer, vs.net will no longer generate corresponding class definitions.

There is a picture with the truth:

ExampleSource code: Http://files.cnblogs.com/yjmyzz/website_test.7z

In fact, there are other unpleasant aspects of WebService. See the two problems encountered by WebService today: datatable + namespace.

"Qingshan cannot be covered, after all, East stream", just as IE6 will be replaced by other browsers, asmx technology will gradually fade out of the historical stage. We recommend that you consider new projects, boldly use WCF to replace asmx. In the next blog, I will write a "wcf10-minute speed-up" to help asmx fans who have never been familiar with WCF eliminate the fear of WCF, quickly get started with WCF.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.