I have asp.net application. where on 2 web pages i have dropdown on each page. i want to populate the User list in drop down. so as usual i wrote the method FillUserDropDown() in common helper class.
and accessing this method on both page loads. but I am passing the Drop down control as parameter to this method so that method appears generic for all type of fill drop downs. Is this standard way? my seniors are avoiding me to passing the control as parameters.
So what is the best practice for this scenario? Please guide me.
To databind is better. But this is also acceptable just that you can let ASP.NET 'fill' it in automatically if you databind (it will generate the code for you). Return a datatable or list and and specify declarivly the binding.
Also tell your seniors that it's ok to do that too. If you've written the code already leave it.
Call Method By this way
FillDropDown(DropDownID, selectListItemText)
Set Below Code In your commonfile
DropDownID.DataTextField =
"TextFieldName";
DropDownID.DataValueField =
"ValueFieldName";
DropDownID.DataSource =
DatasourceName; DropDownID.DataBind();
if (includeSelectItem) {
DropDownID.Items.Insert(0, new
ListItem(selectListItemText,
selectListItemValue)); }
This way you can bind as you said above
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 ;)
I've got a Page, a GridView using an ObjectDataSource with a SelectMethod and a DropDownList. The SelectMethod, among other things, gets a string-array containing several IDs (to filter the Data) - but I also need it as DataSource for the DropDownList.
Alas, I cannot DataBind the DropDownList inside the SelectMethod since it's null.
An Idea would be to bind this string[] to a Session-Variable, but then I'd have to either re-set it upon every Page_Load or remove it from Session on every other page if I want it to update in case something on the Database changed.
What I'm looking for is some kind of variable that is available both in Page_Load and my ObjectDataSources SelectMethod, but that removes itself upon leaving the page (i.e. navigating to any other page on my Web-Application (preferably without having to call a method on EVERY other Page).
I hope you could understand my problem.
Thanks,
Dennis
As I understand the need to fetch the string array arises from the performance hit that a separate roundtrip will cause. To work around this you may create a separate object to feed your object data source. This object will have two methods one for getting the string array and another for getting the data for the grid (i.e. the select method)
You may then put an object like this in your page and fetch the data in it in a lazy manner. If the object makes a call for any of the data it stores the other part in a field. You can then use the ObjectDataSource ObjectCreating event to pass this object on your page to the ObjectDataSource
protected void odsSomething_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
e.ObjectInstance = YourInsntanceAlreadyInThePage;
}
This way you will avoid the roundtrip.
Also consider making two web service calls at the same time using the asynchronous client calls so that you can make both calls for the same time. If this is viable depends on the flow of your logic.
What I'm looking for is some kind of variable that is available both in Page_Load and my ObjectDataSource's SelectMethod, but that removes itself upon leaving the page (i.e. navigating to any other page on my Web-Application (preferably without having to call a method on EVERY other Page).
In a similar situation, I've used the Items property of the current HttpContext. It's an IDictionary (non-generic), so can hold arbitrary objects keyed by arbitrary objects, and its lifetime is precisely the duration of the current request, so will go away as soon as the request is ended. To use:
// Where you first get the data
HttpContext.Current.Items["SomeKey"] = new [] { "string1", "string2" };
// Where you want to to use the data
var strings = (string[])HttpContext.Current.Items["SomeKey"];
I am new to SharePoint developement and have a few startup problems which I hope you will help me with.
I am trying to make a custom field type and I am using WPS builder to create the project. Right now I have the following files which are all compiling just fine :)
SuperLookup3.cs
SuperLookup3Control.cs
SuperLookup3FieldEditor.cs
SuperLookup3FieldEditor.ascx (controltemplate)
fldtypes_SuperLookup3.xml (XML)
I have tried look at this example but I just can't get it to work.
My questions
How is the relationsships between the files?
I can see an override of UpdateFieldValueInItem() which is setting the value to the selected item of a dropdown list. But this method is never called (when debugging). How can this be?
Some general advice would be to post this question to the SharePoint Stack Exchange site (if this answer is unsatisfactory), since there are a lot more SharePoint developers there.
From what I understand of that example, it seems to be quite a complex Custom Field Type to start with (given that it has multiple values). There's a good straightforward and pretty well explained tutorial on MSDN that you might want to try out: Walkthrough: Creating a Custom Field Type
Here's a brief explanation of your files (and the classes they contain):
This is the main class of your field, which derives from the SharePoint field base class (SPField). Your naming seems to indicate you're creating a lookup derivative; if so, you may wish to derived from SPFieldLookup.
This is the class the creates the form control displayed on a list item's New, Edit, and Display forms (but not the List View). It's a go-between for the forms and the item's value for this field.
&
This is the section displayed on the Add/Edit Column page. I would expect 3. to have the ending '.ascx.cs' instead of '.cs', since it is the code-behind for 4.; which may be the cause of your problem. This control sets up your field; associating the class in 1. to the list.
This is the field declaration. It says to SharePoint "Hey, I've created my own field; go look here to find it.", and directs SharePoint to the class in 1., which makes the field available on the Add Column page.
We have a Gridview, which gets filled via a DataSource. The datasource's SelectMethod is a function in the BL class, which calls a Stored Procedure that returns 2 Result-sets. The first result set is supposed to fill the gridview, so it's returned via the "return" keyword, and that works fine. The second result set is for later use (we're not separating them into 2 SP's because the query applies the same logic to get both result sets, and it's a long logic, so we don't want to run it twice). Our question is how to save the second result-set for the later use.
We initially thought of creating a global member in the BL class, and saving the result-set to it. But the problem is that when we need to use the second result-set, we're not in the same class where the gridview is, and that other class creates an instance of its own of the BL class, and of course that object doesn't have the data (the data is in the object created by the aspx page in which the gridview resides).
So then we thought of passing an "out" parameter the datasource's SelectMethod, and the method would save the second result set to that out parameter. But that's not working. I think we don't know how to tell the method that a parameter is "out". The way we pass the other parameters is by defining a method that is attached to the OnSelecting event, and then we pass them so:
e.InputParameters["schoolCode"] = currentSchoolCode;
e.InputParameters["levelCode"] = currentLayer;
Etc. However, we don't know how to tell the method that a parameter is "out". When we googled a little, all we could find was how to tell the method if a parameter is an output parameter - that is, passed to the SP as an output parameter. But that is not the case here.
So we will be very grateful if you help us find the solution for:
"Telling" the method that a certain parameter is "out", in order to get the value into it.
thanks.
Hmm... not quite understand your concern, but, how about this? pass your dataset to presentation layer and then:
dataset.Tables(0)
dataset.Tables(1)
or
DataReader.NextResult()
I have created custom MembershipUser, MembershipProvider and RolePrivoder classes. These all work and I am very happy with it, apart from one thing. I have an extra field in the "Users" table. I have an overridden method for CreateUser() that takes in the extra variable and puts it into the DB.
My issues is that I want to be able to have this called from the Create User Wizard control. I have customized the control to have a drop down to populate my extra field. I have used the following code to store that piece of info but I am at a loss of how I either use the profile or call my custom CreateUser Method:
// Create an empty Profile for the newly created user
ProfileCommon p = (ProfileCommon)ProfileCommon.Create(CreateUserWizard1.UserName, true);
// Populate some Profile properties off of the create user wizard
p.CurrentLevel = Int32.Parse(((DropDownList)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("clevel")).SelectedValue);
// Save profile - must be done since we explicitly created it
p.Save();
Thank you for any and all help
Jon Hawkins
I think your solution is the "easiest" you're going to get. You could create your own wizard and call the correct method, but that's a lot more work.
The only thing I could recommend is using the OnCreatedUser event instead.
reference: 4guysfromrolla
This is not the answer but I found a work around, would still like to know if someone could answer the question directly...
public void UpdateCurrentLvl_OnDeactivate(object sender, EventArgs e)
{
int level = Int32.Parse(((DropDownList)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("clevel")).SelectedValue);
MyMembershipUser myUser = (MyMembershipUser)Membership.GetUser(CreateUserWizard1.UserName);
myUser.CurrentLVL = level;
Membership.UpdateUser(myUser);
}
In my first CreateUserWizardStep if put the method above to fire on deactivate. As at this point it has inserted the user into the DB I can get the User out, cast to my MembershipUser class, set the variable and all the update method.
As I say this is a work around from the way I would liked to have solved it but it works.
Thanks
This is also incredibly hacky, but in the past when I've had to do similar things, I've just crammed the extra value into an unused parameter, like the password reset question or answer. Though, I'm not entirely sure how you'd manage this using the wizard.
It's ugly, but as long as it is explicitly documented (to be safe, I'd comment on the method itself as well as anywhere you reference it) it will work fine.
It's also a lot less work than creating your own wizard.