ASP.Net: When the Master is really a passive-aggressive Slave.



  • In ASP.Net Web Forms pages, jQuery ready() function is not triggered when there is a partial postback, you need a specific Microsoft library (Sys.* namespace) to listen to partial postback events and re-bind whatever ready() did (if you need it). To link this Sys library you have to put a ScriptManager control on the page.

    The ScriptManager has a quirk: there must be only one and it has to be declared within FORM tags (in the BODY). This is usually not a problem, unless the page relies on a Master Page (late-bound templating control that has placeholder containers) which itself needs a ScriptManager to power Ajax menus; because the javascript and the body are in two different placeholder containers in the Master, when there is a partial postback the scripts in the HEAD won't see the ScriptManager in the BODY, and the Sys calls will fail.

    This is a bit of a perfect storm but when it happens you have two options: not using Ajax widgets in the Master Page, or putting your javascript code within the page BODY.

    One more pleasant aspect of Master Pages: at run-time the Master will rename controls to avoid name conflicts with the slave (or its own Master as they can be nested), so if you need to access controls by ID in javascript your end up with things like this:

    $('#<%=ShippingAddress.ClientId %>').val($('#<%=BillingAddress.ClientId %>').val());
    

    (You have the option of forcing static names, but this will cause some widgets to shit themselves down the road when someone else will use the Master Page).



  • and the WTF is...?



  • TRWTF is Web Forms. Admittedly, the old AJAX libraries are monolithic and full of complete baloney. Thankfully, MS has learned enough lately to refrain from trying to make web stateful. If only other frameworks did the same.


  • Considered Harmful

    @Ronald said:

    $('#<%=ShippingAddress.ClientId %>').val($('#<%=BillingAddress.ClientId %>').val());

    I find it much easier to reference dynamic elements with a selector that references the ID of a static element (eg #mycontainer > input:text) or class name.



  • @grinderofl said:

    TRWTF is Web Forms. Admittedly, the old AJAX libraries are monolithic and full of complete baloney. Thankfully, MS has learned enough lately to refrain from trying to make web stateful. If only other frameworks did the same.

    The good thing with Web Forms is that you can ajax-enable a web application just by dragging controls from a toolbox (or even by using the contextual menu) and it works pretty well in all browsers. You can build a complete data-driven application with collapsible panels, calendars, photo galleries, etc. without writing a single line of code, not even going in the HTML source. You can bind stuff to web services, generate device-specific content, etc. in a jiffy.

    But what you gain in simplicity and shorter time-to-market you lose in flexibility; the moment you try to do something remotely non-vanilla with those widgets you open a can of worms. If you need cascading listboxes within a gridview that is part of a master page, you are in for a treat. It's like that scene in Appollo 13.



  • @joe.edwards said:

    @Ronald said:
    $('#<%=ShippingAddress.ClientId %>').val($('#<%=BillingAddress.ClientId %>').val());

    I find it much easier to reference dynamic elements with a selector that references the ID of a static element (eg #mycontainer > input:text) or class name.

    Sure, as long as you control the elements. The problem is when you use a widget like a Listview or Gridview with dynamic content; you don't decide how the control is rendered. As an example, a string column in a Gridview will usually become a bunch of SPAN in read-only mode and a series of textboxes in Edit mode; while for some reason a boolean column will be a checkbox in both modes but disabled in read mode. There is no easy way to put a specific class on the items in one specific column.


  • Considered Harmful

    @Ronald said:

    Sure, as long as you control the elements. The problem is when you use a widget like a Listview or Gridview with dynamic content; you don't decide how the control is rendered. As an example, a string column in a Gridview will usually become a bunch of SPAN in read-only mode and a series of textboxes in Edit mode; while for some reason a boolean column will be a checkbox in both modes but disabled in read mode. There is no easy way to put a specific class on the items in one specific column.

    Point taken, though you might be able to get better markup with a control adapter.



  • @joe.edwards said:

    @Ronald said:
    Sure, as long as you control the elements. The problem is when you use a widget like a Listview or Gridview with dynamic content; you don't decide how the control is rendered. As an example, a string column in a Gridview will usually become a bunch of SPAN in read-only mode and a series of textboxes in Edit mode; while for some reason a boolean column will be a checkbox in both modes but disabled in read mode. There is no easy way to put a specific class on the items in one specific column.

    Point taken, though you might be able to get better markup with a control adapter.

    With ASP.Net you have three possible ways to build a web application: Web Matrix, Web Forms and MVC. And with each there is a bit of incest, like Razor.


    Most people now use MVC. Instead of having monolithic pages, it's all about routing and flow. It reminds me of J2EE servlets. See this interesting blog post



    Unfortunately as you know there are sometimes external factors forcing the selection of a specific technology... Web Forms won't go away anytime soon.



  • @Ronald said:

    The good thing with Web Forms is that you can ajax-enable a web application just by dragging controls from a toolbox (or even by using the contextual menu) and it works pretty well in all browsers. You can build a complete data-driven application with collapsible panels, calendars, photo galleries, etc. without writing a single line of code, not even going in the HTML source. You can bind stuff to web services, generate device-specific content, etc. in a jiffy.

    But what you gain in simplicity and shorter time-to-market you lose in flexibility; the moment you try to do something remotely non-vanilla with those widgets you open a can of worms. If you need cascading listboxes within a gridview that is part of a master page, you are in for a treat. It's like that scene in Appollo 13.

    Pretty mirrors my sentiments exactly. You can do custom stuff but you do need a good understanding how the controls work.

    Also the Page LifeCycle can be a bitch because it is really counter-intuitive, Page_Load on a child control happens before Page_Load on the parent control which can cause weird things happening with variable assignment and exception handling.


  • Considered Harmful

    Control adapters are about whipping Web Forms into shape so you don't have to switch to a new stack (actually, they predate the others); but, you knew that.



  • After reading this, now I don't have to wonder why all the MS shops I've worked with didn't have any clue of how HTTP (session, cookies, authentication, certificates, etc) works.



  • @ubersoldat said:

    After reading this, now I don't have to wonder why all the MS shops I've worked with didn't have any clue of how HTTP (session, cookies, authentication, certificates, etc) works.

    It is totally possible to have a web developer using ASP.Net that does not understand the difference between client and server-side, and that does not even prevent them from doing their job, writing unit tests, etc. I've seen this. But I also met java developers with 5 years experience who had never heard of the word "classpath". I don't think the iPhone generation will fare much better.



  • @ubersoldat said:

    After reading this, now I don't have to wonder why all the MS shops I've worked with didn't have any clue of how HTTP (session, cookies, authentication, certificates, etc) works.

    I love the usual "MS shops are clueless" crap being stated as if it was fact. Most of the WTF systems I have to deal with are PHP or JS based but experience is just as anecdotal as yours.



  • @grinderofl said:

    Thankfully, MS has learned enough lately to refrain from trying to make web stateful. If only other frameworks did the same.
     

    Well the reality is that any web app that is of use at all is in fact stateful.  There are several approaches depending on what you need to do but the purist, stateless web is a thing of theoretical nature at best.  You might as well delegate that stuff to a framework rather than fucking it up several times before you get it right yourself.  Spend your time writing your app rather than fighting reality. 

     



  • @Ronald said:

    The ScriptManager has a quirk: there must be only one and it has to be declared within FORM tags (in the BODY). This is usually not a problem, unless the page relies on a Master Page (late-bound templating control that has placeholder containers) which itself needs a ScriptManager to power Ajax menus; because the javascript and the body are in two different placeholder containers in the Master, when there is a partial postback the scripts in the HEAD won't see the ScriptManager in the BODY, and the Sys calls will fail.

    This is a bit of a perfect storm but when it happens you have two options: not using Ajax widgets in the Master Page, or putting your javascript code within the page BODY.

     ... Or use a ScriptManagerProxy, since it was included in the framework for exactly the scenario you are describing.  It's OK to pick on Web Forms, but at least be correct when you do it.



  • $('#<%=ShippingAddress.ClientId %>')

    This is so painful to look at. In order to access a variable, you have to write:

    • a dollar sign
    • parentheses
    • single quotes
    • a pound sign
    • angle brackets
    • percent signs
    • an equal sign



  • That jQuery snippet is pretty WTF. I have no idea why you would want to do that.



  • @grinderofl said:

    TRWTF is Web Forms. Admittedly, the old AJAX libraries are monolithic and full of complete baloney. Thankfully, MS has learned enough lately to refrain from trying to make web stateful. If only other frameworks did the same.
     

    Pretty much.  WebForms are awful and outside of internal LOB-style apps (where you can control the environment) I can't imagine a use case where you wouldn't rather choose MVC, but even with WebForms you'd best use some third party UI controls (i.e. Telerik) since they're basically thick clients just on the web.  At least they got that MVC right... it's a shame that so many people are still clueless about ASP.NET MVC and think that WebForms is all there is.



  • @Ronald said:

    This is a bit of a perfect storm but when it happens you have two options: not using Ajax widgets in the Master Page, or putting your javascript code within the page BODY.

    ... or not using postbacks, which suck ass anyway.



  • @Ronald said:

    With ASP.Net you have three possible ways to build a web application: Web Matrix, Web Forms and MVC.

    Or just build your WebAPI in plain-jane .ashx handlers, and the site itself in plain-jane HTML and JavaScript. That's what I do. And I'm always right.



  • You can turn most of the stuff you don't like off (The viewstate is the biggy), and you got a pretty decent way of putting together a set of website components. I don't get the hate for the framework, it works pretty well and is well documented. The only thing that is a little difficult as I said is the event sequence can be counter-intuitive in some places.

    Newer versions of the framework have taken some of the features of MVC (strongly typed models, routing etc), so they are there if you need them.

    I think MVC is the better framework, but WebForms really isn't that bad.



  • @blakeyrat said:

    Or just build your WebAPI in plain-jane .ashx handlers, and the site itself in plain-jane HTML and JavaScript. That's what I do. And I'm always right.

    Or if you are a hipster use NancyFX and/or Service Stack.



  • @lucas said:

    @blakeyrat said:
    Or just build your WebAPI in plain-jane .ashx handlers, and the site itself in plain-jane HTML and JavaScript. That's what I do. And I'm always right.

    Or if you are a hipster use NancyFX and/or Service Stack.

    No I don't want MORE frameworks, the point is to REMOVE frameworks so I don't have to deal with their bullshit. ASP.net comes with everything you need out-of-the-box, you don't need WebForms, you don't need MVC bullshit, you're already set.

    The reason you don't see more people going that route is because a LOT (maybe even most) programmers don't fucking understand how the web works. So they're pretty much incapable of writing a simple JSON API call without packing in 25 MB of MVC framework bullshit and spending hours of setup time to save them (net) 20 lines of code.

    KISS.



  • Seriously?



  • Mother of God... I actually agree with blakeyrat!!! *shoots self*

    Seriously though if for whatever reason you can't move away from WebForms, you can do the ASHX trick with standard HTML/CSS/JS on the front end, and make API calls.  It's not as good as using the actual WebAPI (which admittedly I don't know much about), but it works.  The only annoying part is you can only have one method per ASHX, so you end up having very fine-grained files for each specific thing you want to do, but in reality it's not that bad and the fine-grained detail forces you to be explicit about what your method calls are doing; no DoStuff() method that does fifteen different things.

    Couldn't you also do something with web services in the same way?  Just create a bunch of web services and Ajax call them from pure HTML UI?



  • @blakeyrat said:

    No I don't want MORE frameworks, the point is to REMOVE frameworks so I don't have to deal with their bullshit. ASP.net comes with everything you need out-of-the-box, you don't need WebForms, you don't need MVC bullshit, you're already set.

    The reason you don't see more people going that route is because a LOT (maybe even most) programmers don't fucking understand how the web works. So they're pretty much incapable of writing a simple JSON API call without packing in 25 MB of MVC framework bullshit and spending hours of setup time to save them (net) 20 lines of code.

    KISS.

    Actually the only reason I don't do things the way you are saying is because of KISS and the fact that many don't understand how the web works.  You build it using the things they do understand so that your replacement can do your job (of course part of that depends on the quality of replacements you tend to get).



  • The whole point of the webapi/NancyFX/ServiceStack is that you don't have to do shit like that in ashx, the default routing and other kit is already setup for you can you can just get on with it. You might save some time on some of the most trivial examples.

    Also HTML pages are no good when I need to generate mark-up server side. So I am going to need something like MVC or WebForms to have sensible separation of Markup from my Server-side logic.

    ASP.NET MVC / NancyFX and Service Stack pretty close to the bone anyway.

    Also why do we care if we have a couple more dlls referenced on server?

     



  • @ObiWayneKenobi said:

    It's not as good as using the actual WebAPI (which admittedly I don't know much about), but it works.

    "the actual WebAPI" is actually a add-on to MVC. It works, and it gives you a few nifty features (like XML or JSON serialization, automagically), but I still don't think it's worth the effort to learn it. I could be wrong.



  • @locallunatic said:

    Actually the only reason I don't do things the way you are saying is because of KISS and the fact that many don't understand how the web works. You build it using the things they do understand so that your replacement can do your job (of course part of that depends on the quality of replacements you tend to get).

    That is genuinely a concern. It hasn't come up for me yet, since I'm basically the only back-end developer here.



  • @lucas said:

    Also HTML pages are no good when I need to generate mark-up server side.

    I've never had to do that. There are tons of JavaScript templating engines out there to do your mark-up.



  • @blakeyrat said:

    @lucas said:
    @blakeyrat said:
    Or just build your WebAPI in plain-jane .ashx handlers, and the site itself in plain-jane HTML and JavaScript. That's what I do. And I'm always right.

    Or if you are a hipster use NancyFX and/or Service Stack.

    No I don't want MORE frameworks, the point is to REMOVE frameworks so I don't have to deal with their bullshit. ASP.net comes with everything you need out-of-the-box, you don't need WebForms, you don't need MVC bullshit, you're already set.

    The reason you don't see more people going that route is because a LOT (maybe even most) programmers don't fucking understand how the web works. So they're pretty much incapable of writing a simple JSON API call without packing in 25 MB of MVC framework bullshit and spending hours of setup time to save them (net) 20 lines of code.

    KISS.

    I mostly agree. The more you rely on frameworks the more you open the door to side-effects and unexpected bugs, and you have to learn the specifics of the framework in addition to the underlying technology. And one of the side-effects of frameworks is idiot savant programmers, but that's not .Net specific.

    But in some situations it's not possible to change the "architecture". The client has a huge code base, a bunch of developers who do only Web Forms using VB.Net connected to a DB2 database via a weird layer of COM objects, and they need someone to do a quick prototype of a specific business feature? Going in and starting by saying: forget Web Forms, use C#, drop your COM layer and switch to WCF + SQL Server is a no-go. The best you can do is do the prototype so they get what they asked for, and you submit free of charge a "technology roadmap" for them to consider. Sometimes the client had no clue that his technology is weird and they are happy to make a long term migration project out of it; but most of the time they just want to have that form where they can search the inventory from a Google-like textbox and that's the end of it.

    I guess things are different when you are an employee. As a contractor I enjoy running away from problems and I don't care if they want a WTF as long as I get my money and don't have to stay there too long; I don't mislead clients on purpose, but I don't try to educate them too hard either. Took me years to find the right balance of "mercenary" and "missionary" in my approach - this requires a high level of tolerance to WTFs.



  • @locallunatic said:

    @blakeyrat said:

    No I don't want MORE frameworks, the point is to REMOVE frameworks so I don't have to deal with their bullshit. ASP.net comes with everything you need out-of-the-box, you don't need WebForms, you don't need MVC bullshit, you're already set.

    The reason you don't see more people going that route is because a LOT (maybe even most) programmers don't fucking understand how the web works. So they're pretty much incapable of writing a simple JSON API call without packing in 25 MB of MVC framework bullshit and spending hours of setup time to save them (net) 20 lines of code.

    KISS.

    Actually the only reason I don't do things the way you are saying is because of KISS and the fact that many don't understand how the web works.  You build it using the things they do understand so that your replacement can do your job (of course part of that depends on the quality of replacements you tend to get).

    I subscribe to that. KISS from a platform perspective and KISS from a development cycle perspective are not always compatible.



  • @ObiWayneKenobi said:

    Couldn't you also do something with web services in the same way?  Just create a bunch of web services and Ajax call them from pure HTML UI?

    A web service with an HTML UI is a web page. Throw in the Ajax part and ask that it should be all done in HTML with no javascript coding and you get Web Forms with the Ajax toolkit.

    This reminds me of a client who did not want a database (they did not need a database, databases are stupid, databases are broken, databases are a thing of the 90s etc) so they suggested instead "something like a Windows Service that would handle I/O persistence and could be interfaced using a SQL-like dialect".



  • @blakeyrat said:

    @lucas said:
    Also HTML pages are no good when I need to generate mark-up server side.

    I've never had to do that. There are tons of JavaScript templating engines out there to do your mark-up.

     

    You are a fucking idiot. If you can't possibly understand that ..

    Seriously you are a fucking dickhead and shouldn't be allowed near a keyboard



  • @lucas said:

    You are a fucking idiot. If you can't possibly understand that ..

    Seriously you are a fucking dickhead and shouldn't be allowed near a keyboard

    Well by all means, call me an idiot and a dickhead instead of explaining your opinion.


  • Trolleybus Mechanic

    @Ronald said:

    Ajax toolkit.
     

    Fucking fuck that fucking fuckity fuckery with a fucking fuckstick, for fucking fuck-of-a-fuck fuck's sake!



  • @Lorne Kates said:

    @Ronald said:

    Ajax toolkit.
     

    Fucking fuck that fucking fuckity fuckery with a fucking fuckstick, for fucking fuck-of-a-fuck fuck's sake!

    There is something highly enjoyable with this toolkit, especially the Rating extender (voting stars). For some reason when it's used in a GridView within a Master Page, in Read Mode the first row won't work, it always show 1 star even if you hard-code the value to 2 or 3. It's not data-related because when you sort the gridview on a different column the first row still won't show the right amount of stars. But if you go in Edit Mode on the first row then you see the right value and you can change it, but then the next row which is in Read Mode has the bug. I was this* fucking close to screenshot stars and use a CSS background-image property to work around that, but then the client decided that they wanted a swipe and three columns to sort what people dislike, don't care or like, so fuck the stars.

    * this is what I meant by "this close":




  • @LoztInSpace said:

    @grinderofl said:

    Thankfully, MS has learned enough lately to refrain from trying to make web stateful. If only other frameworks did the same.
     

    Well the reality is that any web app that is of use at all is in fact stateful.  There are several approaches depending on what you need to do but the purist, stateless web is a thing of theoretical nature at best.  You might as well delegate that stuff to a framework rather than fucking it up several times before you get it right yourself.  Spend your time writing your app rather than fighting reality. 

     

    Methinks you are missing the point here - attempting to make web stateful only takes you to a point where you're eventually going to start losing performance due to the massive viewstate that gets passed left and right, as well as completely forgoing maintainability (which is not to say that an idiot couldn't make shit out of bread with MVC, but it takes a lot more effort provided you can follow at least simple guidelines), and so on and so forth. I'm not gonna delve in that subject because it's been chewed through a gazillion times on every single website that has any relation to ASP.NET. Call me a purist all you want, but I prefer having complete control over the HTML that the client receives over something completely obscure which, if gone wrong, has the capability to make you scratch your head for days on end.



  • @Ronald said:

    Took me years to find the right balance of "mercenary" and "missionary" in my approach
     

    I have a hard time squaring this staggering morsel of wisdom with how you casually mentioned keying a police car because they were in the way.


  • Trolleybus Mechanic

     Let's see how many "you've got no idea what you're talking about" triggers this one sets off:

    @grinderofl said:

    Methinks

    @grinderofl said:

    massive viewstate that gets passed

    @grinderofl said:

    Call me a purist

     Too many, can't look for any more. Must go throw birds at pigs.

     

     



  • @dhromed said:

    @Ronald said:

    Took me years to find the right balance of "mercenary" and "missionary" in my approach
     

    I have a hard time squaring this staggering morsel of wisdom with how you casually mentioned keying a police car because they were in the way.

    Churchill was a drunk. Hoover was a crossdresser. MLK was abusing underage boys. Obama got a scholarship for foreign students under a false identity. Sean Penn used to slap Madonna around. All great men have flaws, THEY ARE JUST HUMAN



  • @Ronald said:

    All great men have flaws,
     

    The inverse is also true.



  • @dhromed said:

    @Ronald said:

    All great men have flaws,
     

    The inverse is also true.

    All non-great men have non-flaws?

    I prefer the converse: All flaws have great men.



  • @Ben L. said:

    All non-great men have non-flaws?
     

    That's an awkward phrasing, but yes.



  • @Ronald said:

    Churchill was a drunk. Hoover was a crossdresser. MLK was abusing underage boys. Obama got a scholarship for foreign students under a false identity. Sean Penn used to slap Madonna around. All great men have flaws, THEY ARE JUST HUMAN
     

    Interesting choice of "great" men.

    Churchill and MLK – Probably on most people's lists.

    Hoover – Herbert, J. Edgar or W. H. (of vacuum cleaner fame)? (Yeah, Wikipedia would undoubtedly tell me which one was a crossdresser, if I gave a rip.) Herbert is "generally ranked no higher than average among US Presidents" (last sentence of introduction). J. Edgar was unquestionably powerful, but that does not necessarily make him great; his abuse of that power makes him not-great. W. H. did not invent the vacuum cleaner; he was just in the right place at the right time, and recognized a good business opportunity when he saw it. Great? Maybe.

    Obama – Controversial, historically important; definitely. Great? That's for history to decide, but I wouldn't bet on it.

    Sean Penn – Bwahahaha!



  • @HardwareGeek said:

    @Ronald said:

    Churchill was a drunk. Hoover was a crossdresser. MLK was abusing underage boys. Obama got a scholarship for foreign students under a false identity. Sean Penn used to slap Madonna around. All great men have flaws, THEY ARE JUST HUMAN
     

    Interesting choice of "great" men.

    Churchill and MLK – Probably on most people's lists.

    Hoover – Herbert, J. Edgar or W. H. (of vacuum cleaner fame)? (Yeah, Wikipedia would undoubtedly tell me which one was a crossdresser, if I gave a rip.) Herbert is "generally ranked no higher than average among US Presidents" (last sentence of introduction). J. Edgar was unquestionably powerful, but that does not necessarily make him great; his abuse of that power makes him not-great. W. H. did not invent the vacuum cleaner; he was just in the right place at the right time, and recognized a good business opportunity when he saw it. Great? Maybe.

    Obama – Controversial, historically important; definitely. Great? That's for history to decide, but I wouldn't bet on it.

    Sean Penn – Bwahahaha!

    Congrats, Ronald, you caught one!



  • @morbiuswilters said:

    @HardwareGeek said:

    @Ronald said:

    Churchill was a drunk. Hoover was a crossdresser. MLK was abusing underage boys. Obama got a scholarship for foreign students under a false identity. Sean Penn used to slap Madonna around. All great men have flaws, THEY ARE JUST HUMAN
     

    Interesting choice of "great" men.

    Churchill and MLK – Probably on most people's lists.

    Hoover – Herbert, J. Edgar or W. H. (of vacuum cleaner fame)? (Yeah, Wikipedia would undoubtedly tell me which one was a crossdresser, if I gave a rip.) Herbert is "generally ranked no higher than average among US Presidents" (last sentence of introduction). J. Edgar was unquestionably powerful, but that does not necessarily make him great; his abuse of that power makes him not-great. W. H. did not invent the vacuum cleaner; he was just in the right place at the right time, and recognized a good business opportunity when he saw it. Great? Maybe.

    Obama – Controversial, historically important; definitely. Great? That's for history to decide, but I wouldn't bet on it.

    Sean Penn – Bwahahaha!

    Congrats, Ronald, you caught one!

    I was about to defend Obama and Sean Penn, but now you made it look like I was dishonest in my statement so it's useless. You should change your alias for MORBIUS THE TATTLETALE.



  • @Ronald said:

    I was about to defend Obama and Sean Penn, but now you made it look like I was dishonest in my statement so it's useless. You should change your alias for MORBIUS THE TATTLETALE.

    I never understood why people thought Obama was historically important. (Then again, I guess "historically important" just means "people think it's important", so maybe I'm wrong..)



  • @morbiuswilters said:

    @Ronald said:
    I was about to defend Obama and Sean Penn, but now you made it look like I was dishonest in my statement so it's useless. You should change your alias for MORBIUS THE TATTLETALE.

    I never understood why people thought Obama was historically important. (Then again, I guess "historically important" just means "people think it's important", so maybe I'm wrong..)

    He's the first black president, he won a Nobel prize and he is the first indonesian islamic mole to ever get access to the Football device.



  • @Ronald said:

    He's the first black president

    So what?

    @Ronald said:

    he won a Nobel prize

    Again, so what?

    I guess it's just historical because people are retarded, not because it actually matters. It would be like me saying "This dump I'm taking is historically important" and then if I can convince 100 million people, it becomes true.


Log in to reply