I'm wanting to update a record in my database which has two values, one is the ID, and one is the "description". The ID can never be changed, however I'm relying on the use of strongly-typed features to do it. So, I have the following:
Inherits="System.Web.Mvc.ViewPage<Business>"
Which is fine as it allows me to get everything back. The problem is when I use the following line:
<%= Html.TextBox("BusinessID", ViewData.Model.BusinessID, new { disabled = "disabled", style = "width:50px;", #class = "uppercase", maxlength = "4" })%>
With the disabled = "disabled" option it doesn't recognise the BusinessID and therefore doesn't pass it back to the controller which, in turn has problems binding the object up.
Not that you'll need it, but here's the controller action:
[HttpPost]
public ActionResult EditBusiness(Business business)
{
if (!ModelState.IsValid)
return View(business);
// update business here
_contractsControlRepository.UpdateBusiness(business);
return RedirectToAction("Businesses");
}
Any ideas why this is happening? I didn't realise form elements were completely hidden on postback when they're disabled. I don't want the users editing that particular field. I've also tried Html.DisplayFor(b=>b.BusinessID) without any luck.
display the id like this
Html.Hidden("BusinessID", ViewData.Model.BusinessID)
<%=Model.BussinessID %>
this way you will have the id for the binding in the hidden tag
and you will display the value in the label
or you can use anything else that you want yo can do like this also
<input type="text" value="<%=Model.BussinessID %>" contentEditable="false">
and put the hidden somewhere in the form
instead of Html.Textbox you can use Html.Hidden("BusinessID", ViewData.Model.BusinessID)
You always have the option of either "hard-coding" the html element, or writing your own html helper method to do it.
public static string DisabledTextBox(this HtmlHelper helper, string name, object value)
{
return String.Format(#"<input type="text" name="{0}" id="{0}" disabled="disabled" value="{1}" />", name, value);
}
Is there a particular reason you are displaying the id? if not then leave it out and on your controller simply use TryUpdateModel() instead.
or is that not what your asking?
edit
<%= Html.TextBox("name","value", null, new { style="readonly"}) %>
Edit 2
You might think about doing a route like //site/controller/yourbusinessid
then you can use the id as it's passed to your controller and you can then, in your view, simply use <%= Model.BusinessId %> as a string.
Related
I am working on an MVC 2.0 C# web Applciation. In one of my form, i am using LabelFor() html helper.
I am using the following syntax:
<%=Html.LabelFor(model=>model.Addedon)%>
Here, for this label i would like to associate a initial value that is DateTime.Now
I tried some thing like this:
<%=Html.LabelFor(model=>model.Addedon,new{value=DateTime.Now})%>
But, i am getting an error saying that there is no over load for this helper taking two arguments.Please help
UPDATED:
The form is create form/ add form which makes an insert operation. So, i am building a model and updating that model to the database.
In that model, i have a field called createdby. So, i need to associate this value with the username logged in and doing the insert operation.
So, how to associate this username value with the model field and i need to display as label so that it will be read only field.
Hope this makes clear..
LabelFor is only for, you guessed it, rendering a <label> element.
It also uses the [Display] and [DisplayName] attributes, so you can have a strongly-typed label with custom name.
What you're after is probably this:
<div>
<%= Html.LabelFor(model => model.Addeon) %>
</div>
<div>
<%= Html.DisplayFor(model => model.Addeon) %>
</div>
So the LabelFor will generate the property name description (e.g. 'Addeon'), while the DisplayFor will render the property value. DisplayFor can use the [DisplayFormat] attribute if you need custom formatting. You can set the default property value in the view model's constructor:
public class ViewModel
{
[Display(Name = "My awesome date")]
public DateTime Addeon {get;set;}
public ViewModel()
{
Addeon = DateTime.Now;
}
}
[EDIT]
Actually, your edit would make for a good second question instead of putting it here. Anyway, in your situation I'd create a dedicated view model that would hold the properties you need (e.g. user name) and would be filled in controller. Everything else would be conceptually the same - view would bind to the view model.
I'm trying to change the emitted name of the html input created by #Html.HiddenFor.
The code I'm using this:
#Html.HiddenFor(e => e.SomeProperty, new { #id = "some_property", #name = "some_property" }
Now this works for the id, however it doesn't work for the name. Now I don't really care for the id now, I need the name to change, because that's the one that get's posted back to the target server.
Is there
A property I can apply on SomeProperty in my model?
A way in the Html.HiddenFor to override the name property?
Or am I stuck to do a plain <input ...> by hand?
You need to use the Html.Hidden (or write out the <input ...> by hand) instead of the Html.HiddenFor
#Html.Hidden("some_property", Model.SomeProperty, new { #id = "some_property" })
The goal of the strongly typed helpers (e.g the one which the name end "For" like HiddenFor) is to guess the input name for you from the provided expression. So if you want to have a "custom" input name you can always use the regular helpers like Html.Hidden where you can explicitly set the name.
The answer from unjuken is wrong because it generates invalid HTML.
Using that solution generates TWO name attributes:
<input Name="some_property" name="SomeProperty" id="some_property" type="hidden" value="test" />
So you will have Name="some_property" AND name="SomeProperty" which is INVALID HTML because an input can only have ONE name attribute! (although most browers happen to take the first Name="some_property" and don't care about the second one...)
If you use:
#Html.HiddenFor(e => e.SomeProperty, new { #id = "some_property",
#Name = "some_property" });
Notice the capital "N" in #Name. It´ll work.
I was curious as to why specifically overriding the name attribute wouldn't work. Unless I capitalized it (i.e. new {#Name = 'somename'} ), then it doesn't seem to work. As others have pointed out, this only works because it generates duplicated name attributes and Chrome cleans it up.
I looked at the latest MVC source code to figure out what is going on. Consider the following snippet from the GenerateInput method in DefaultHtmlGenerator.cs:
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
if (string.IsNullOrEmpty(fullName))
{
throw new ArgumentException(
...
}
var inputTypeString = GetInputTypeString(inputType);
var tagBuilder = new TagBuilder("input");
tagBuilder.TagRenderMode = TagRenderMode.SelfClosing;
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("type", inputTypeString);
tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
We can see here, the problem is that, regardless of whatever name property you provide, it will be overridden by the last call to MergeAttribute, which will use whatever logic it is that assigns to the variable fullName from the GetFullHtmlFieldName method.
I sort of understand why they enforce this behavior, guessing it has something to do with controlling the names used in the postback to guarantee it works with the model binder.
In any case, to make this happen, I say just manually construct the input element and don't use the razor view helper.
never worked for me (aspnet.core)
I used plain
<input type="hidden" id="#myid" name="#myname" value="#Model.prop" />
and worked like a charm. No need for HtmlHelper HiddenForModel.
I have a model with various properties but the one of interest is a List of another type of Model.
For example:
public class User
{
public string Name { get; set; }
public string Description { get; set; }
public IEnumerable<UserInterest> Interests { get; set; }
}
I then use an Editor Template within my view to render out a view for each item of the model items.
#Html.EditorFor(x => x.Interests)
The EditorFor template looks something like:
#model Interest
<div>
#Html.HiddenFor(x => x.Id)
#Html.TextBoxFor(x => x.InterestText)
#Html.CheckBoxFor(x => x.Delete)
....
</div>
Something very similar to the accepted answer here: Model Containing List of Models (MVC-3, Razor)
My question is - how would you from the client-side (jQuery) create a new item within the property without going back to the server. I currently have a rough way of doing it whereby I post the data back to my controller which returns the model back with a new blank item within the Interests property.
This seems to be overkill making a HTTP request and not very elegent. I was thinking of using jQuery .Clone() but not entirely sure on what I'd need to do in terms of naming the elements and clearing existing values.
So does anybody have any suggestions. I'm hoping to get more opinions and different approaches.
You can simply create the Textbox and checkbox on the fly and add that to the DOM. When saving it, Use jQuery ajax to post that data ( new record data) to an action method and save it there. Return a status back (Succcess /Falied) from your action method to your client side code ( your callback function of jQuery ajax/post) and check it there. If it is success, Show a success message to the user and append the new item to the existing list.
Sample jSFiddle : http://jsfiddle.net/carwB/2/
If you want to return some complex data ( ex : All new records with its id etc..) along with the status, you may return JSON from your action method.
EDIT : To keep your Model binding works with the newly added dynamic elements, you need to follow the naming convention of the elements.
The trick is to keep the id property value of the html element in this format.
CollectionName_ItemIndex__PropertyName
and name property value in this format
CollectionName[ItemIndex].PropertyName
I created a sample working program and explained it how it works Here based on your requirements.
In such situations I prefer to use client templating. You send data to server with ajax and then receive JsonResult. Look at JsRender this is javascript lib without jQuery dependency.
1.Create two partial view one is for list item and second one is creation
2.First partail view should be inside the div which has id 'divMdeolList'
3.and Creation view will have the code like that
#using (Ajax.BeginForm("SubmitData", new AjaxOptions { UpdateTargetId = "divMdeolList" }))
{
#Html.TextBoxFor(x => x.InterestText)
<p>
<input type="submit" value="Create" />
</p>
}
4. And then create a ActionResult type action on controller that will render the partialview
public ActionResult SubmitData(YourModel model)
{
//Do : save the record
return PartialView("FirstPartailView", model);
}
This will update the View without postback
As far as I can tell, there are 3 ways to create a DropDownList in an ASP.NET MVC View:
Hand code the HTML manually
<asp:DropDownList ID="someID" runat="server"></asp:DropDownList>
<%= Html.DropDownList("someID") %>
I think we can all agree that #1 is (generally) a waste of time.
With #2, it appears to be the "WebForms" way of doing it, but has an advantage in that if you're writing a View you can have access to the object you've created via inline code that occurs after it. For example:
<asp:DropDownList ID="someID" runat="server"></asp:DropDownList>
<%
someID.SelectedIndex = 0;
string someString = someID.SelectedValue.ToString();
%>
This does not appear to be possible with #3.
The nice thing that I've discovered about #3 (the HTML Helper way) is that by passing it a string, it sets the Name and ID to the string as well as uses the string to search the ViewData dictionary and auto-generate the respective tags for the DropDownList based on the SelectList that was added to the ViewData dictionary that was added in the calling Controller.
// controller code
ViewData["someID"] = new SelectList(someMethod().ToList());
For the life of me, I cannot figure out if there is a way to auto-generate the tags with <asp:DropDownList> or if I have to manually create them myself.
What's generally the best approach for implementing a DropDownList in ASP.NET MVC?
<%= Html.DropDownList("name", new SelectList(someEnumerable, "valueProperty", "textProperty")) %>
where someEnumerable is a property on your viewModel.
for example:
class Person
{
int id;
string name;
}
class myVM
{
IEnumerable<Person> people;
}
<%= Html.DropDownList("name", new SelectList(Model.people, "id", "name")) %>
Edit dont make the SelectList in your controller, this is view specific code and belongs in the view, just send your IEnumerable in the viewmodel.
For some reason I'm stuck on this. I need to filter results from a View based on a DropDownList in the same view. The basic idea is this: I have a list of providers that belong to various partners, but the provider list contains ALL the providers together (for all partners). I need to be able to display the providers by partner when someone wants to see just that partner (otherwise, the default listing will be ALL providers). My view currently is the "default" (showing all), but for some reason Im sitting here staring at the monitor (for the last 2 hours!) trying to figure out how to filter these results.
Any suggestions where to start/how to do it?!
EDIT: If you want to do this with jQuery and AJAX (which will provide a better user experience because only the subdivisions list will refresh), see this tutorial.
If I understand correctly, you basically want to do a WebForms-style postback.
Let's say you have a control with countries and country subdivisions (e.g. states, provinces, etc). When the country changes, you want the appropriate subdivisions to display.
So this would be view:
<% using (Html.BeginForm()) { %>
<%=Html.DropDownList("Address.CountryId", new SelectList(Country.GetAll(), "Id", "Name"), new { onchange = "this.form.submit();" })%>
<%=Html.DropDownList("Address.CountrySubdivisionId", new SelectList(CountrySubDivision.GetByCountryId(Model.CountryId), "Id", "Name"))%>
<input type="submit" name="btnSubmit" value="Submit"/>
<%} %>
This is the key to getting the dependent list to filter:
new { onchange = "this.form.submit();" }
And in the controller, you'd have something like this:
[AcceptVerbs(HttpVerbs.Post)]
public ViewResult Index(string btnSubmit)
{
if (btnSubmit == null)
{
// return the view displayed upon GET
}
else
{
// process the submitted data
}
}
In the above code, if the form submission was triggered by changing the value in a dropdown, btnSubmit will be null. Thus, the action you are POSTing to can tell whether or not the user meant to finalize her changes.
To add upon the earlier answers.
To create a drop down (in ASP .NET MVC 3) I did the following:
Add code to Index.cshtml
#using (Html.BeginForm())
{
#Html.DropDownList("EmployeeId", (SelectList)ViewData["EmployeeId"])
<input type="submit" name="btnSubmit" value="Submit"/>
}
Add code to YourModelNameController.cs in the default ActionResult for Index()
public ActionResult Index()
{
//create a selectlist
var employeeList = from el in db.Employee select el;
ViewData["EmployeeId"] = new SelectList(employeeList, "EmployeeId", "TmName");
return View(modelName);
}
There are many ways to skin this cat. Here's one.
Enclose your DropDownList in a form with METHOD=GET.
<form action="" method="get">
<select name="provider">
<option>1</option>
<!-- etc -->
</select>
</form>
Then, in you controller, filter based on the value of provider that was passed in. Remember to treat it as a Nullable parameter so that you can have some kind of behavior when it's empty.
Without posting some of your current code, it's tough to get much more specific than that.
Let's assume that you're probably passing a model to the view and that model is a list or IEnummerable of partners. What you want to do is restrict the list. In order to do that add a drop down list in the view and fill it with some possible partners. This can be done either by putting a list in ViewData or expanding the model passed back to the view. Both have advantages. Now when you change the drop down reload the page but append a parameter which is the filter. In the controller check for that parameter in the action, if it isn't present then return an unfiltered list, if it is then apply a filter and return the list. The view will just dumbly display whatever you give it.
As for the filtering you might want to try using LINQ.
You probably want a parameter to your controller action, maybe a (nullable?) id of the provider, to filter the results already when you get them from DB. Then just use the same view to list them, and request a new list if the dropdownlist changes.
Best solution I know is that one.
http://gridmvc.codeplex.com/SourceControl/latest