I've inherited an ASP.NET Webforms applications that deals with numerous similar views of data. However, because of the templates and because it uses the control which also has separate templates for various modes (EditItemTemplate, ItemTemplate, etc.) I have several pages that have numerous repetitive definitions of how to display each piece of data.
EDIT: For clarity, the duplications are of small chunks of the overall UI, not duplication of the entire UI. A column definition in a subtable of a grid inside a formview can get repeated 4 or more times (Both the ItemTemplate and the EditItem Template of the FormView would have both ItemTemplates and EditItemTemplates for the particular master table volumn.)
(Needles to say this makes making and verifying changes drastically harder than it should be.)
If this was XAML, I could declare the repetitive parts as Resources and reuse them to achieve a level of DRYness. (Don't Repeat Yourself)
I've made some code snippets for adding new items to keep additions consistent, but it doesn't help with making sure edits happen everywhere consistently.
Are there any tools to help with this in ASP.NET Webforms or am I stuck with WET code? (Actually, Write Everything Twice is a understatement for this situation. Some pages have up to 8 repetitions of the same UI for columns)
If you have the exact same UI, then I would question why you need multiple controls in the first place.
If they truly are that identical, then why not consolidate the controls into a single control and use Object oriented techniques to alter the code implementation that uses the single control in the code behind.
For example, you might have a dictionary of Action delegates that all use the same UI based on parameters a different implementation gets selected. If you do this correctly (say, using an MVP pattern) then you can make this highly testable and create unit tests to test your different implementations.
Related
Trying to craft a way for our designers to create custom asp.net webforms for our customers. The basic idea is that we have a general set of fields that can be saved, with each customer using a subset of those fields, each customer may have it's own names for similar concepts (ie one customer may use 'patient' and another 'customer'). Staying in customer context will help the designers build the correct form to meet the customers needs.
Now to do this I need to get as much as I can into the design experience as possible. I have a set of custom controls that derive from base controls like asp:TextBox and implements an interface to allows me to iterate over the controls and insert values from a data store, or fetch values to persist (Done). All of these controls need to be bound to a data point in my record object. I have a metadata system set up to allow the binding, but where I am running into trouble is in getting the list of available fields into a UITypeEditor. Namely, I haven't figured out how to (at design time) set the customer context on the form, and then access and use that value on each controls custom property editor (also at design time). Is this possible? Am I looking at this problem the wrong way? A form always has 1 and only one customer context. So in my forms project, each form will have a different customer id set to it.
As a second question how can I debug these editors? There is an expectation of web context in the editors, but there is no asp.net property grid. and even if there was, the editors are winforms components that wouldn't run in a browser.
I can include the code I currently have if it simplifies the problem, but even a simplified example is a half dozen classes.
I resolved these issues, posting here in case a general solution can be useful to anyone in the future.
I was able to get around this problem a bit by going the other way. My parent Page iterates over it's controls, and sets the CustomerId on all the controls that implement a specific interface.
As for debugging. Some refactoring got me to a place where I can easily swap out the webforms specific parts of my implementation for testing.
I'm sure I'm missing something obvious here.
I have a about twenty data-bound GridViews, each of which share some common features. Let's say they're all lists of people, and every one starts with about 10 columns which are complex linkButtons with hovers etc, they're all the same. The remainder of these grids, which are extremely wide, consist of completely different columns; it's just the first 10 (of about 100) columns which are duplicated.
Hence I have this chunk of code which handles those 10 database columns and renders that html out, using 10 Eval() statements etc. It's the same code in each GridView, it's repeated 20 times over and that's obviously not cool.
I can't just chuck it in a user control or a custom control because I need the GridView to do the column headers and all that stuff. I can of course put a user control in for one column and render everything I want that way ("eval" works nested like that), but it doesn't give me the column headers, which are also complex.
So that's the question: is there any way I can break out of a templated GridView control to abstract this repeated code? I almost want a sort of server-side include or pre-processed thing, as I just need to repeat the text really, but I need to do it before asp.net tries to compile it. I could use a custom control to render any HTML I like, but that doesn't solve the problem as it's asp.net code I need to generate, not HTML.
Can't you subclass from Gridview and implement the common functionality for all the 10 gridviews there and then have further subclasses that implement the specific functionality for the specific gridviews? I've done this successfully with Pages (the most base class had authentication logic that all subclasses inherited)
When creating dynamic controls based on a data source of arbitrary and changing size, what is the official way to track exactly how many controls need to be rebuilt into the page's control collection after a Postback operation (i.e. on the server side during the ASP.NET page event lifecycle) specifically the point at which dynamic controls are supposed to be rebuilt? Where is the arity stored for retrieval and reconstruction usage?
By "official" I mean the Microsoft way of doing it. There exist hacks like Session storage, etc but I want to know the bonafide or at least Microsoft-recommended way. I've been unable to find a documentation page stating this information. Usually code samples work with a set of dynamic controls of known numbers. It's as if doing otherwise would be tougher.
Update: I'm not inquiring about user controls or static expression of declarative controls, but instead about dynamically injecting controls completely from code-behind, whether they be mine, 3rd-party or built-in ASP.NET controls.
This greatly depends on the problem at hand, and the type of controls you're recreating. Are they all simple text boxes or various different complex custom user controls. the main thing here is: if you want your dynamic control to regain state after a post-back, you have to re-create it in the Init phase of a page life-cycle.
Anyway. There's nothing like a Microsoft way or Microsoft recommended way basically. When you're dynamically adding several simple controls of the same type a hidden field with a count would do the trick, but when you have several complex controls other ways would have to be used. You could still hidden fields and save control's full type strings in them (ie. System.Web.UI.WebControls.TextBox) and re-instantiate them. But think of an even more complex example of putting various controls on different parts in the page... And initializing them to a specific state. That would be a bit more challenging. Hence no Microsoft way... The recommended way is to recreate in Init phase. And that's it.
Everything can be solved, but sometimes one took a wrong direction in the UI and things could be done easier using a different approach.
Additional explanation
This state-full technique of ViewState that Asp.net uses is considered the worse culprit with web developers in general. That's why Asp.net MVC developers think the new framework is bliss since its much more suited to the state-less HTTP protocol. Me being one of them. :D
I've got a set of ASP.Net pages that display a number of asp:TextBox fields depending on the number of entries in a configuration file. I know that the number of fields won't be going above 10 or so. Given that, should I declare a sufficiently large number of text boxes in markup, or should I dynamically create the textboxes in the code-behind?
There are advantages and disadvantages to each approach, which is why I'm having trouble choosing. The advantage to the dynamic approach is that the application is more flexible - even if the number of fields goes above 10, my application will be able to scale. The disadvantage is that I'm now mixing markup and logic - my application is inserting textboxes and literals (for the labels) into the page. This will make future maintenance harder because not all of the fields are in the .aspx file.
The advantage to declaring a large form and then just showing or hiding the necessary fields is that it keeps logic and markup separate. The disadvantage, of course, is that I lose flexibility. If the number of fields goes beyond the amount I anticipate (and there is a small risk of that) I have to revisit the application to add more fields.
So, StackOverflow, which would you choose? More importantly, why would you choose your approach?
One option is to combine the best of both worlds. If you put your textbox in a repeater, you can then dynamically control how many repeater rows are displayed, while having the controls statically declared.
I would definitely go with the dynamic approach because, as you say, this will scale if requirements change in the future and you will not be sending unnecessary markup to the browser.
I don't see how using static fields avoids the issue of mixing logic and markup as you will need to use code to hide the unwanted controls.
I have recently come across a number of projects where developers have been leaving their ASPX pages relatively free of markup, in favor of placing all logic inside of ASP.NET user controls. While I understand and respect the use of user controls for enabling code reuse, entire pages built in an ASCX just feels incredibly wrong. I was hoping that this mindset would go away now that ASP.NET MVC is here, but I'm seeing the same pattern, even in new projects.
Am I being overly anal, or does this just smell?
It only makes sense when the user control is actually re-used. These tend to be smaller component parts.
In our case its quite useful for creating bespoke applications that use a subset of usercontrols, this way pages that are not used can just be deleted and managed that way, keeping all the UserControls in one place to use at a later date.
Interesting point - using ASP.NET MVC, I sped up one of our pages by several seconds by removing a user control that was loaded inside a loop - loading the UC takes a noticeable amount of time, which is fine for a single instance, but a pain for multiple.
On MVC I've used a user control to hold a set of fields that I re-use between both the create and edit forms, rather than re-typing; I've also used them in WebForms as self-contained chunks of functionality (file upload controls, message posting, etc).
I agree that there is a smell for single-use controls - in fact I've been guilty of that in the past, and I'm just now going through and starting to remove them.
One useful usage: if you have <% ... %> code blocks on your master page, you won't be able to programatically manipulate the controls. Shunting such code blocks into user controls removes this problem, which we've had to do in one case.