I'm in the need to create a custom field type that renders like a LinkValue field. Instead of forwarding the browser to a different page, I would like to execute JavaScript code (in order to use OpenPopUpPage) depending on several parameters (maybe stored in SPFieldMultiColumnValue?).
What is the best way to approach the requirement?
This has to be the best reference on custom field types from Bjorn Furuknap
Customizing the User Experience of SharePoint: Custom fields deep dive
There is some pain involved in custom fields types though, in his own words
“Looking back I think it would have
been easier, and less painful, to eat
my own eyes.”
Related
I am employing a logic similar to the suggestion present in the Microsoft documentation https://msdn.microsoft.com/en-us/library/cs58sb90(v=vs.110).aspx to retrieve the custom attributes given to the parameter of a method.
However, I find this approach expensive as it uses reflection to retrieve the custom attributes, I am wondering if there is any better approach to this problem than using reflection?
The short answer as far as I am aware is no, reflection is the standard and probably only way to retrieve attributes.
However, attributes are fixed in the type metadata at compile-time, which means you will only ever have to inspect them once for each type during the lifetime of your program, and they won't change in that time unless your code is doing some really wacky runtime type construction (e.g. with Reflection.Emit). Even if you don't know the exact type of any object your code requires the attributes of, you could still cache the type's attributes in a dictionary to save looking them up again, if you're really that concerned about performance.
Unfortunately I'm relatively new to MVC so what I am trying to do might be quite simple or not even possible in MVC.
I have a series of template classes in a library which can have template added, change or removed between versions. What I am trying to do is create a page that will allow for the user to select from a drop down list which template they wish to work on and then once they have selected the template be able to populate the properties of the template through text boxes, drop down lists, date selectors etc.
Whilst I could in theory create a View for each of the different templates, I would like to avoid that as if the templates can be added/changed/removed with newer versions of the library, I would like to avoid having to rewrite the Views each time that happens.
Does anyone have any suggestions on how I might be able to achieve this or know of existing references dicussing this?
If I've missed out any information which would be of use please let me know.
Thanks for any help/advice in advance.
Satal
Without writing the code, what you are looking for is a component that builds html based on what model/object it is passed to satisfy the population of that model via a web browser.
I dare say that this is possible!
An easy or easier route would be:
Decorate the properties within your template models with attributes that would dictate what sort of input control they require.
Also decorate the properties with an attribute that specifies the name of the attribute.
Create a component that accepts a model/type and creates HTML to satisfy the input of that type. Of course this must be rendered within a form.
On postback/submit to your action use the Request["{propertyName}"] to get the value of input fields to populate the properties.
Your controller action will accept the name of the Template so that you know which model to create
System.ComponentModel.DataAnnotations is a good place to start before writing your own custom attributes.
With asp.net mvc you can use the annotation
[Required (errormessage="This is required")]
How can I create something like this:
[Required (errormessage="ERRORXX")]
So I can look up in a database what this ERRORXX is and display it on my form. Now my form displays ERRORXX.
How can I create something that solves my problem?
Thx!
Just an idea: why not pull the error messages from a resx file? I think this is the common way of doing this. It even allows you to localize your error messages easily.
I think that by using a resource file (resx file) it's even easier to change the error messages later on. A resx file can be opened and edited in Word Pad for example. You don't need to access a database with username/password, query it, etc.
Localizing ASP.NET MVC Validation
Globalizing ASP.NET MVC Client Validation
Take a look here too:
Model Validation & Metadata in ASP.NET MVC 2
Customizing ASP.NET MVC 2 - Metadata and Validation
The default route to take is with Resources.
However, I understand your pain :) The way I've achieved it is a little unusual, but I'll give you a quick rundown.
In our project, using resource files is not an option as its way too limited for our purposes, the details of which I won't bore you with now! :)
At it's most basic principle, we're setting the errorMessage property of the validation attribute to some sort of "key", and then just using that as a way to lookup the correct (languaged) response in our CMS database, when the validation fails (in our case using MVC, when we update the model and check the state - all at Controller level).
This is the same principle as using the resources (by specifying "ErrorMessageResourceName" and "ErrorMessageResourceType"), but you get to do what you want with it.
To be clear, we originally extended the RequiredAttribute (as one example) with our own stuff, including putting in properly named arguments to allow us to retrieve a sensible CMS value from the database later on. To be extra clear, we're using MVC and custom HtmlHelpers to render our own ValidationControls, which are what ultimately consume the custom values from our custom annotations, etc - None of this affects the dumbed-down principle here though, which is to just use "errorMessage" , or something like it, as a way to look up the actual message from where YOU want to, and WHEN you want to.
I think you mean you want to read/use attribute declarations for a given property?
If so, you could either make your own RequiredAttribute class (to allow adding new or more appropriate properties as you wish). See: Attributes Tutorial
I'm using ASP.NET MVC 2.
Keeping it simple, I have three payment types: credit card, e-check, or "bill me later". I want to:
choose one payment type
display some fields for one payment type in my view
run some logic using those fields (specific to the type)
display a confirmation view
run some more logic using those fields (specific to the type)
display a receipt view
Each payment type has fields specific to the type... maybe 2 fields, maybe more. For now, I know how many and what fields, but more could be added. I believe the best thing for my views is to have a partial view per payment type to handle the different fields and let the controller decide which partial to render (if you have a better option, I'm open). My real problem comes from the logic that happens in the controller between views. Each payment type has a variable number of fields. I'd like to keep everything strongly typed, but it feels like some sort of dictionary is the only option. Add to that specific logic that runs depending on the payment type.
In an effort to keep things strongly typed, I've created a class for each payment type. No interface or inherited type since the fields are different per payment type. Then, I've got a Submit() method for each payment type. Then, while the controller is deciding which partial view to display, it also assigns the target of the submit action.
This is not elegant solution and feels very wrong. I'm reaching out for a hand. How would you do this?
It's one for thing for, say, an Order object to not really care about the particular payment type--just knowing that there is a PledgedAmount and a DepositedAmount property, for example, is enough for that class to do its job (e.g., "don't allow myself to go to Shipped status if order is not charged, via whatever payment method, I don't really care, as long as it's charged somehow I'm cool").
It's another thing for the UI to not really care: you either write a switch to load the right view and be done with it, or you end up creating a dictionary-like collection of fields, rules, and validation metadata and let the UI generate itself dynamically.
For example, I took the latter approach when I was adding international address support for one of my applications. I abstracted addresses into a common set of fields: AdministrativeArea, Municipality, etc, and defined an AddressScheme class which defined AddressFieldRules for each field, stating whether or not it was required, if a regex should be applied, if there is a specific set of allowed values, etc. It was appropriate since we could add or remove countries to the allowed list at any time without recompiling and redeploying the application; the UI could dynamically generate itself based on the AddressScheme, which itself was loaded from the database. Sweet.
But are you really going to be adding payment types (a) with great frequency or (b) without re-compiling your application? Sometimes you really do need an actual Toaster instead of a Breakfast Cooking Machine w/ Bread and Other Yeast-Based Goods Browning Module, so just add a switch or a dictionary that maps a type to the correct view: I think it's perfectly acceptable for the UI to have to be able to distinguish among these types, and, more importantly, for you to custom-write and tailor the presentation of each type--but the higher-up parts might benefit from some abstraction. I talked about that in my answer to a different question related to billing.
In your example, you can share common code for steps 1, 4, and 6, but delegate to specific UI methods and views for steps 2, 3, and 5. And the world will still spin round.
My two cents. Good luck!
It sounds like you have three distinct workflows, each pertaining to a different payment method chosen by the user. While you only explicitly indicate steps 3 and 5 as having payment specific concerns, it would seem that everything after step 1 must display payment specific information (unless in step 4 the user isn't confirming payment specific information, and in step 6 their receipt doesn't indicate how they've paid).
In this case, you'll probably create a bigger mess for yourself trying to combine all of this into a single workflow rather than creating distinct controllers for each payment type, factoring out any common behavior for reuse by each of the three paths.
As an aside, while you indicated that you weren't using an interface, the reason you gave seems a little troubling. It sounded like you might have used an interface if the payment types contained the same fields. Interfaces are for defining behavior contracts, so you shouldn't be using them to define common data.
I am working on a Windows Forms app for quite some time now, and I really find myself doing more typecasts in the GUI code than I ever did in my underlying business code.
What I mean becomes apparent if you watch the ComboBox control that accepts some vague "object" as it's item.
Then you go off and may display some DisplayMember and a ValueMember and so on.
If I want to retrieve that value later I need to typecast my object back to what it was. Like with strings getting the value takes
string value = (string)combobox1.SelectedItem;
Since there are generics in the Framework for quite some time now, I still wonder why in the Hell not one control from the standard toolbox is generic.
I also find myself using the .Tag property on ListViewItems all the time to keep the displayed domain object. But everytime I need to access that object I then need another typecast.
Why cant I just create a ComboBox or ListView with items of type ListViewItem
Am I missing something here or is this just another example of not perfectly well thought through controls?
While the criticism of "didn't use generics" can't be fairly applied to controls developed before their existence... one must wonder about WPF controls (new in .NET 3.0, after generics in .NET 2.0).
I checked out the AddChild method in ComboBox. It takes an object parameter (ugh).
This control is intended to be used primarily via XAML. Was this done this way because there is no way to specify a type parameter in XAML? (aside, is there no way to specify a type parameter in XAML?)
Sorry to have no definitive "Why" answer, just sharing the common misery of needing to cast when working with the UI.
I dont think you're missing anything.
It's just that these classes were created back in the pre-Generics days, and WinForms is simply not cutting edge enough for MS to spend a lot of time changing or extending the API.
I often create wrapper classes for controls. This allows me to use generics. This is often in conjunction with Reflection, which is not type safe at compile time, but can be at run time.
A common source of this problem, I think, is not separating your view/presentation logic from your in-memory data model logic. Which, unfortunately, is an architecture fault that WinForms and the Visual Studio GUI designer are complicit in.
WinForms and the VS designer do not encourage the programmer to separate the management of their data objects from the form classes themselves. It would probably be better if the ComboBox ListViewItem objects didn't offer any support for arbitrary objects, either via generics or Object collections..
Unless you are hacking together something of limited use and lifetime, you should try to avoid storing references to individual data objects right in your controls or forms. They should be managed separately, and if they need to be referenced, it should be done via a model management class designed for the particular type of view class you're working with.
A simple-ish bandage for the problem, though, might be to "map" the text representations that you place into the ComboBox or ListView to the original objects, using a Dictionary field member on your Form class. It's not an ideal solution, but gives you at least a half-step of indirection between your data and your UI controls, which can make your code easier to maintain.
Edit: This is admittedly separate from the ListViewItemCollection class exposing Object instances... The official defense is likely to be that they wanted to support the standard IEnumerable and ICollection interfaces. But there's no reason they couldn't have also provided type-specific overrides of these methods, since it is designed explicitly to store ListViewItem instances. So I have no answer for you on that particular question.
Well, if you data-bind your controls to a DataBindingSource, you can get at your data that way, but AFAIK that's still not strongly typed. If you are displaying multiple parameters/aspects of a single business object, you can bind to that, then access the (strongly typed) members instead -- of course, this all goes back to Turbulent Intellect's answer, which is better separation between model and view. Still, I agree that generic-based typing would help.
It is possible (you can make your own generic controls, if you wish), but the form designer that comes with Visual Studio will freak out if you do this. You'll have to do stuff without it.
You aren't the first one to think of this, and Microsoft has already received a fair share of criticism from the public for this. Let's hope they add support for this in the future.