Looking for some help on some names for a project I'm currently working on. I don't have a compsci degree so I don't know what to call this.
I have a method called TryToGetSetValue(Direction direction, object value, object valueOnFail)
Then there would be a Direction enum
public enum Direction
{
ModelToForm,
FormToModel
}
Background
This is a legacy ASP.NET application. The models, database, and mainframe are designed poorly. I can't put in MVP or MVC patterns yet (too much work). ASP.NET code is a ridiculous mess (partial pages, single-page design, 5x the normal amount of jQuery, everything is a jQuery UI dialog). I'm just trying to put in a bridge so then I can do more refactoring over the next year.
I have ~200 fields that need to be set on a GET and written back on a POST.
I trying not to x2 these 200 fields and have 400 lines of code to support.
What would you call my method? enum? Is there so other form of binding that would be easy to use instead? I'm not a fan of the DetailsView or FormView built-ins of ASP.NET WebForms.
You probably want a Property
Just my $0.10 here, but how about:
public void AccessProperty(PropertyAccessType accessType, object value, object valueOnFail){...}
public enum PropertyAccessType
{
ModelToForm,
FormToModel
}
Related
I've inherited a code base written in ASP.Net MVC 4. Every post method takes a FormCollection. Aside from annoyance of having to access the values through quoted strings, it also leads to drawbacks such as not being able to use things like ModelState.IsValid, or [AllowHtml] attributes on my ViewModel properties. They actually did create ViewModel classes for each of their views, (though they are pretty much just direct wrappers around the actual Entity Framework Model classes), but they are only used for the GET methods.
Is there anything I'm missing about FormCollection that gives a reason why this may have actually been a good idea? It seems to only have drawbacks. I'd like to go through and "fix" it by using ViewModels instead. This would take a good bit of work because the ViewModels have properties that are interfaces and not concrete classes, which means either writing a custom binder or changing the ViewModels.
But perhaps there's something I'm missing where it makes sense to use FormCollection?
Is there any good reason to use FormCollection instead of ViewModel?
No. I have following issues.
Issue - 1
In case FormCollection is being used...It will be mandatory to Type Cast the Primitive Type Values un-necessarily because while getting the entry of specific Index of the System.Collections.Specialized.NameValueCollection, value being returned is of type String. This situation will not come in case of Strongly Typed View-Models.
Issue - 2
When you submit the form and goes to Post Action Method, and View-Model as Parameter exists in the Action method, you have the provision to send back the Posted Values to you View. Otherwise, write the code again to send back via TempData/ViewData/ViewBag
View-Models are normal classes, created to bind data to-from Views
Issue - 3
We have Data Annotations that can be implemented in View Model or Custom Validations.
ASP.Net MVC simplifies model validatons using Data Annotation. Data Annotations are attributes thyat are applied over properties. We can create custom validation Attribute by inheriting the built-in Validation Attribute class.
Issue - 4
Example you have the following HTML
<input type="text" name="textBox1" value="harsha" customAttr1 = "MyValue" />
Question : How can we access the value of customAttr1 from the above eg from inside the controller
Answer : When a form get posted only the name and value of elements are posted back to the server.
Alternatives : Use a bit of jQuery to get the custom attribute values, and post that along with the form values to action method
Another option is to rather put what you got in your custom attributes in hidden controls
That's the reason, I would always prefer to use View-Models
The only advantage I can think of is if you want to use the automatically generated controller provided when you don't specify a EF model to be strongly typed to. In that case, your Create and Edit actions will use the FormCollection object as it is a reliable, pre-existing artifact of the framework to work with for this purpose. Perhaps the previous developer chose this option while creating his controllers, and stuck with it since Visual Studio must know what it's doing :)
But, in reality, I would never recommend this headstart of a few seconds. It's always better to build out viewmodels, I would recommend looking at the effort to move in that direction if only for maintenance purposes. With model binding and strongly typed views and html helpers, you are much more likely to reduce the number of run-time errors as a result of changing some magic string and not realizing it until your page blows up.
Ok, I see the general consensus here is that it isn't liked. To offer another perspective, I've always liked using the formcollection passed into the controller on POST actions. It offers the use of the TryUpdateModel method from the controller which will map the collection to your strongly typed class. TryUpdateModel also has overloads that allow you to white list the properties of the model that you want to allow to be updated.
if (TryUpdateModel(viewModel, new string[] { "Name" }))
{
//Do something
}
It still allows all the model binding you want, but helps to keep anything other than the "Name" property on my viewmodel from being updated.
You can see more about the TryUpdateModel method here:
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryupdatemodel(v=vs.108).aspx
There are always workarounds for getting away from a FormCollection lol.. you can have hidden fields bound to your view model variables in the form to your heart's content.
Form collections mostly emerge from the laziness of creating a view model but still end up taking time trying to get figure out how to get the values out of it in your controller :P
I think it was simply created in the very beginning of MVC as an alternative to using strongly typed views when having very simple forms - back in the days when everyone used ViewBag :) ... and once hey had it in there they couldn't just take it out as simple as that.
Maybe you can use it if you are absolutely sure your view will never have more than one form input? Probably still a bad idea though..
I cant find any recent articles talking about any advantages of form collections.. while strongly typed views are everywhere.
Yes. Sometimes, it can be useful. Here's an example:
Let's say we have in our db "date_and_time_field".
In Razor View, we want to use two form fields. The first one "Date" (maybe with jQuery UI Datepicker). The second one "Hour".
In the Controller Action, we compose the "date_and_time_field" by means of Request.Form["Date"] and Request.Form["Hour"].
There are other scenarios where it can be useful:
A cross-table (with checkBoxes in Razor view)
The collection Request.Unvalidated().Form (maybe this is not part of your question: I don't wanna be off-topic)
The default model binder will do almost everything you need it to do. I resorted to the FormCollection once - only to later figure out how to bind arrays of elements into a collection on the ViewModel.
Just go ViewModel. Better all around, for every reason enumerated.
With form collection you will be able to get all the values inside the form. There can be situations where you may need to pass some additional values from the form which may not be part of your view model.
Just take an example of passing 10 hidden values from the form. The form collection makes sense.
The only difficulty that you may face is type casting. All form collection items that you get will be string; you may need to type cast based on your requirement.
Also model state validation is another area where you may face a challenge.
You can always add the form collection properties to your method signatures. They will automatically be populated by form values with corresponding keys.
Well with Forms Collection you will find a quick way to get the values of a form. Otherwise you have to create a class that mimics the Form Fields and people are sometime lazy to create custom classes for less important/rarely used Forms.
No there is no extra benefit (in fact limited) of forms collection over a custom class as action parameters and it should be avoided whenever possible.
Responding to the title question: yes.
There are some situations that FormCollection needs to be used. For instance, suppose a ViewModel that has a property that implements the 1 to N relation (in concrete case, a TimesheetViewModel with ICollection<TimesheetEntryViewModel>), and the Controller has to perform a validation between the time entries to not get a time collision between the end time of an entry and the start time of the following entry. To mark a related entry with a validation error, how can be the line index be retrieved?
Well, with the default model binding, the index value is lost in the Controller logic. Fortunately, FormController stores the index you used in the View and a more specific validation can be done.
There are type of SPA apps where you have no idea about your model (there is no ViewModel at all and views are created dynamically (for short ;))), so FormCollection is your only choice where you implement custom post validation having entire page input values...
If your view has a knowledge about the model then, of course, you can use your concrete ViewModel object. That's easy ;)
First of all, this is not SQL related.
I have two tables where data shows. (As shown below, pretend the table on the right has no data in it.)
You have to imagine it's a list of items that you can order on the left side, and once you click on an item, it adds it to the table on the right.
This has been the case on our ASPX website, but we're now making/converting that in C#/MVC (See picture below of ASPX version)
I am not asking for code, but reccomendations/advise on how I should do this.
Possibly JQuery, or maybe in the Controller.
In the Aspx.cs
void ArticlesGridViewItemsDisplay_ItemClicked(object sender, Dictionary<string, object> data)
{
using (var dbConnection = DbConnectionFactory.CreateConnection())
{
int materiaalId = Convert.ToInt32(data["MateriaalID"]);
var materiaal = Materiaal.FetchById(dbConnection, materiaalId);
_orderFormData.AddOrderItem(new OrderLineDto(materiaal, 1));
OrderFormRepeater.DataBind();
}
}
You could go the route of using a framework such as Angular and Knockout but both of these is likely to require you to implement a MVC type model on the client in js/json. I've used both KO and ANg with MVC applications and although they are both excellent I've sometimes found them a bit of pig to work with. In your case you appear to have a very simple requrement - its just seems to be basic DOM manipulation and a dynamic selection. Ang/KO frameworks are of course excellent at doing this sort of thing but I wonder it its a bit of an overkill for you? What you've described would be very easy to acheive with a light touch of jQuery. And lets face it jQuery and .Net do have a longer heritage than the new kids on the block.
I know I'm being somewhat vague and thats simply because there is no absolute right answer to this question. It all depends on how you intend to extend the application and on whichever method your most comfortable with. One thing however is clear in my mind: Using a MVC controller for all the work would result in needless requests to server which will be slower UX and increase the burden on the server. Neither of which is desirable. Better by far to keep as much as possible in the browser. And on the server, use WebAPI to respond to you ajax requests, MVC for your POSTs and html GETS.
I wonder how many cages I rattled with these comments... bring on the debate!
This is what the implementation would look like
public class Product
{
public integer id {get;set;}
[MultiLangual]
public string name {get;set;}
}
In the database, name would contain something like:
{en:Pataoto, nl: Aardappel, de: Patat, fr: pommes de terre}
This would contain all the translated fields, that a client has given to his own product.
(in this case: a patato).
In the frontend, this would appear as multiple html elements, which i (somehow) detect which language it is, on submitting the form.
My question is, how would i do this? I'm always stuck on creating the attribute and don't know where to continue...
In my attribute, i shouldn't do a lot, just something like this (i think):
public class MultiLangualAttribute : Attribute
{
public MultiLangualAttribute() : base()
{
}
public override string ToString()
{
return base.ToString();
}
}
But how would i detect everything in my views and create a custom layout for it (this should work with and .
It would only contain text.
Any ideas or a better implementation of above, would be VERY usefull :)
I think the better (arguably) implementation is standard way of application localization.
You define your resources and strings under App_GlobalResources folder you will have to create.
For example you will create file Fruits.resx with all your fruits you want to translate in your system language.
Afterwards you will create Fruits.de.resx, Fruits.es.resx etc, with all the languages you want to have in your website.
It is also possible to update the resources at runtime.
Its too much to describe all the approach in this answer, I would rather provide a link or two with detailed tutorial on MVC application localization:
This is classic ASP.NET MVC localization explanation:
Globalization And Localization With Razor Web Pages
Another explanation of the same thing, little more detailed is here:
ASP.NET MVC Localization: Generate resource files and localized views using custom templates
This should be enough for you to localize your app the standard way.
This is a little more advanced approach, when they use language as part of the URL you accessing.
es.yourdomain.com will be in Spanish, fr.yourdomain.com will be in French:
Localization in ASP.NET MVC – 3 Days Investigation, 1 Day Job
With regards to your approach (storing different languages in the database) here's link to microsoft approach for this. Its much more involved and complex, and I am not sure if benefitting you by its complexity, since you end up using database to fetch every single string in your app. Not the most efficient, but possible approach as well:
Extending the ASP.NET Resource-Provider Model
Hope this all will be of helps to you & good luck
I am tacking a large refactor of a project, and I had asked this question to confirm/understand the direction I should go in and I think I got the answer that I wanted, which is not to throw away years worth of code. So, now begins the challenge of refactoring the code. I've been reading Martine Fowler and Martin Feathers' books, and they have a lot of insight, but I am looking for advice on the ultimate goal of where I want the application to be.
So to reiterate the application a little bit, its a dynamic forms system, with lots of validation logic and data logic between the fields. The main record that gets inserted is the set of form fields that is on the page. Another part of it is 'Actions' that you can do for a person. These 'Actions' can differ client by client, and there are hundreds of 'Actions'. There is also talk that we can somehow make an engine that can eventually take on other similar areas, where a 'person' can be something else (such as student, or employee). So I want to build something very de-coupled. We have one codebase, but different DBs for different clients. The set of form fields on the page are dynamic, but the DB is not - it is translated into the specific DB table via stored procs. So, the generic set of fields are sent to the stored proc and the stored proc then decides what to do with the fields (figure out which table it needs to go to). These tables in fact are pretty static, meaning that they are not really dynamic, and there is a certain structure to it.
What I'm struggling specifically is how to setup a good way to do the dynamic form control page. It seems majority of the logic will be in code on the UI/aspx.cs page, because its loading controls onto the webpage. Is there some way I can do this, so it is done in a streamlined fashion, so the aspx.cs page isn't 5000 lines long? I have a 'FORM' object, and one of the properties is its' 'FIELDS'. So this object is loaded up in the business layer and the Data layer, but now on the fron end, it has to loop through the FIELDS and output the controls onto the page. Also, someway to be able to control the placement would be useful, too - not sure how do get that into this model....
Also, from another point of view - how can I 'really' get this into an object-oriented-structure? Because technically, they can create forms of anything. And those form fields can represent any object. So, for example, today they can create a set of form fields, that represent a 'person' - tomorrow they can create a set of form fields that represent a 'furniture'. How can I possibly translate this to to a person or a furniture object (or should I even be trying to?). And I don't really have controls over the form fields, because they can create whatever....
Any thought process would be really helpful - thanks!
How can I possibly translate this to to a person or a furniture object
(or should I even be trying to?)
If I understand you correctly, you probably shouldn't try to convert these fields to specific objects since the nature of your application is so dynamic. If the stored procedures are capable of figuring out which combination of fields belongs to which tables, then great.
If you can change the DB schema, I would suggest coming up with something much more dynamic. Rather than have a single table for each type of dynamic object, I would create the following schema:
Object {
ID
Name
... (clientID, etc.) ...
}
Property {
ID
ObjectID
Name
DBType (int, string, object-id, etc.)
FormType ( textbox, checkbox, etc.)
[FormValidationRegex] <== optional, could be used by field controls
Value
}
If you can't change the database schema, you can still apply the following to the old system using the stored procedures and fixed tables:
Then when you read in a specific object from the database, you can loop through each of the properties and get the form type and simple add the appropriate generic form type to the page:
foreach(Property p in Object.Properties)
{
switch(p.FormType)
{
case FormType.CheckBox:
PageForm.AddField(new CheckboxFormField(p.Name, p.Value));
break;
case FormType.Email:
PageForm.AddField(new EmailFormField(p.Name, p.Value));
break;
case FormType.etc:
...
break;
}
}
Of course, I threw in a PageForm object, as well as CheckboxFormField and EmailFormField objects. The PageForm object could simply be a placeholder, and the CheckboxFormField and EmailFormField could be UserControls or ServerControls.
I would not recommend trying to control placement. Just list off each field one by one vertically. This is becoming more and more popular anyway, even with static forms who's layout can be controlled completely. Most signup forms, for example, follow this convention.
I hope that helps. If I understood your question wrong, or if you'd like further explanations, let me know.
Not sure I understand the question. But there's two toolboxes suitable for writing generic code. It's generics, and it's reflection - typically in combination.
I don't think I really understand what you're trying to do, but a method using relfection to identify all the properties of an object might look like this:
using System.Reflection;
(...)
public void VisitProperties(object subject)
{
Type subjectType = subject.GetType();
foreach (PropertyInfo info in subjectType.GetProperties()
{
object value = info.GetValue(subject, null);
Console.WriteLine("The name of the property is " + info.Name);
Console.WriteLine("The value is " + value.ToString());
}
}
You can also check out an entry on my blog where I discuss using attributes on objects in conjunction with reflection. It's actually discussing how this can be utilized to write generic UI. Not exactly what you want, but at least the same principles could be used.
http://codepatrol.wordpress.com/2011/08/19/129/
This means that you could create your own custom attributes, or use those that already exists within the .NET framework already, to describe your types. Attributes to specify rules for validation, field label, even field placement could be used.
public class Person
{
[FieldLabel("First name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(1)]
[FormRow(1)]
public string FirstName{get;set;}
[FieldLabel("Last name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(2)]
[FormRow(1)]
public string LastName{get;set;}
}
Then you'd use the method described in my blog to identify these attributes and take the apropriate action - e.g. placing them in the proper row, giving the correct label, and so forth. I won't propose how to solve these things, but at least reflection is a great and simple tool to get descriptive information about an unknown type.
I found xml invaluable for this same situation. You can build an object graph in your code to represent the form easily enough. This object graph can again be loaded/saved from a db easily.
You can turn your object graph into xml & use xslt to generate the html for display. You now also have the benefit of customising this transform for differnetn clients/versions/etc. I also store the xml in the database for performance & to give me a publish function.
You need some specific code to deal with the incoming data, as you're going to be accessing the raw request post. You need to validate the incoming data against what you think you was shown. That stops people spoofing/meddling with your forms.
I hope that all makes sense.
I guess this is a story of how frameworks cheerfully do 95% of what you need, but then frown disapprovingly at that final five percent; inform you that if you want to participate in nonstandard malarky it's your own business, thank you very much, and it'll be here if you decide you want to return to doing things it's good at. Generally speaking it's inevitable that this final five percent will contain some version of a must-have feature.
I have a strongly-typed view which updates a data object. I've used idiomatic MVC2 helpers, eg Html.TextBoxFor(model = > model.Name). I've used Editor templates for nested objects. (My backend is a collection of Mongo documents, so I need to represent complex types).
Then I need a dropdown. It turns out dropdowns are a bit finicky; no problem, I'll make a viewmodel instead of passing in the item directly:
class itemViewModel
{
...
public Item item { get; set; }
public IEnumerable<SelectListItem> dropdown { get; set; }
}
public ActionResult()
{
return View("Update", new itemViewModel(item, dropdown))
}
... that works fine, the dropdown populates. But! my view requires updating:
Html.TextBoxFor(model => model.Name) ->
Html.TextBoxFor(model => model.item.Name)
Great, problem solved. Oops, now my model binding doesn't work. I debug and look at the Request.Form values: Oh. item.Name instead of Name. Makes sense. I tell my Update view to expect an itemViewModel instead, and the binding works.
Oh wait, no it doesn't. Because I have nested objects that use editors. They are strongly typed and they don't know that the model they're receiving is actually a property of the viewmodel. So they're still spitting out Address.City instead of item.Address.City, and the binding fails.
I can think of several workarounds:
Write specialized custom model binder
Put the whole damn form into its own typed editor, so it gets the item model without knowing it's a property
Kill the viewmodel and hack the dropdown using the ViewData dictionary
Quit using the HtmlHelpers and hand-write the whole form
Write my own HtmlHelper extensions that will take a lamba and a model object as parameters.
Put every label/field grouping into an individual editor template.
All of these feel like either overkill or sloppiness. Viewmodels seem to be a clean, helpful approach. Does using them mean that I have to be sloppy in other areas, or reproduce minor variations on sizeable chunks of the framework? I taught myself C# over the last three months (a graphic designer trying to figure out what the hell static typing is with no CS background was probably pretty funny to watch). I work in isolation; there's no one to learn best practices from. I feel like if I don't learn some of them, I'll end up with an unmaintainable dung heap. So, your opinions are appreciated.
Sigh. A couple more hours of Googling and a few shots in the dark, and it appears that there is an unbelievably straightforward way for doing this, using the Bind attribute:
[HttpPost]
public ActionResult([Bind(Prefix="item")] item)
{
//item's complex types populate correctly
}
The attribute seems to be smart enough to reach into the complex types.
I will leave this as a tribute to my own ignorance, and in hopes that some other hapless n00b will find an answer quicker than I did.
Daniel, first off I should say that I commend you on your efforts and taking on .NET , C# and ASP.NET MVC all in one big bite. Ok, so you're frustrated and I relate to that. It's happens to all of us every now and then.
I should let you know that I'm not a fan (not in the least bit, in fact) of ASP.NET MVC (Problems with ASP.NET MVC Framework Design) and so I can't give you a worked out solution to your problem. But here is how I'd like you to see the situation you're in:
You're in a maze and you've made one wrong turn somewhere and you're going deeper into the maze but you're not going to find a way out. So what you need to do is back out till that wrong turn and see if there is another route. So starting from where you are, ask yourself, "why" for every step/change you've made and back up one step at a time asking why. does that make sense? you'll eventually get to a point where you have other alternative ways to tackle the same (original) problem.