I have created a function for doing on validations on textbox entered value based on selection in drop downlist .. ..suppose If the dropdownlist selected item is amount then the entered value in textbox must be in between 10 t0 20 like this i have got two more validations.. for that purpose, I have got one textbox and one dropdwonlist and one button in my view
when i enter value in textbox as 30 and select the drop downlist item as "Amount" and then click on the submit button, the view is not showing any error message and ( if i left textbox as empty and then press submit button its should show error msg but its not showing) (I have written Custom functions for validating these ones on server side)
I have put a breakpoint at a postValues method but its not hitting ...
for that I have done like this (controller part)
public class CrossFieldsTxtboxesController : Controller
{
public ActionResult Index()
{
var itemsforDropdown = new List<SelectListItem> {
new SelectListItem{ Text = "Amount" , Value = "Amount"},
new SelectListItem{Text= "Pound", Value ="Pound"},
new SelectListItem {Text ="Percent", Value ="percent"}
};
ViewData["Listitems"] = itemsforDropdown;
return View("DdlCrossFields");
}
[HttpPost]
public ActionResult PostValues(CrossFieldValidation model)
{
if (!ModelState.IsValid)
{
return View(model);
}
else
{
return RedirectToAction("DdlCrossFields");
}
}
}
and this is my view part
#model MvcSampleApplication.Models.CrossFieldValidation
#{
ViewBag.Title = "DdlCrossFields";
}
<h2>DdlCrossFields</h2>
#using (Html.BeginForm())
{
<div class ="editor-field">
#Html.TextBoxFor(m => m.TxtCrossField)
#Html.ValidationMessageFor(m=>m.TxtCrossField)
</div>
#Html.DropDownList("Listitems",ViewData["Listitems"] as SelectList)
<input id="PostValues" type="Submit" value="PostValues" />
}
and this is my model part
public class CrossFieldValidation
{
public string DDlList1
{ get; set; }
[Required(ErrorMessage = "Quantity is required")]
[Display(Name= "Quantity:")]
[ValueMustbeInRange]
[NumericAttributes]
public string TxtCrossField
{ get; set; }
}
would any one have any idea why its not working for button click , any suggestions also would be grateful
many thanks..
I don't see any place where you specify an action that should handle POST request (PostValues in your case). You can use an overload of Html.BeginForm and specify POST action name explicitly:
Html.BeginForm("PostValues", "CrossFieldsTxtboxes")
If I'm right, your POST requests go to Index action and therefore ModelState.IsValid is not checked there.
You can use client side validation using jQuery Unobtrusive validation plugin. Please check if you have the following keys in your web.config file:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
But note that custom validation attributes require additional JavaScript code to work on client.
I dont see where you are actually calling the method when you do the post - do you have a javscript click handler?
You need to have the method and controller you want to go to in your Html.BeginForm() or you can have something like the below in your view:
#Html.ActionLink("Post Values", "PostValues", "CrossFieldsTxtboxesController", null, new { #class = "postValuesButton", onclick = "return false;" })
Related
So I have this form with this inside it
<div class="form-group">
#*<div class="form-check form-check-box">
#for (int i = 0; i < Model.Features.Count; i++)
{
<div class="form-check form-check-box">
<input class="form-check-input" type="checkbox" asp-for="#Model.Features[i].Selected" value="#Model.Features[i].Text">
<label class="form-check-label" asp-for="#Model.Features[i].Text">#Model.Features[i].Text</label>
</div>
}
</div>
And when I post the form and inspect the properties of the SelectedListItem it looks like this
Even though the Selected should be True because I checked it. Everything else that's in the form gets posted fine, like the text input binds just fine to the string Text property inside my ProductModel, I believe the issue is with the way I'm using the checkbox element properties.
So I can see the checkboxes, and I can check them, etc, but when I post the form, nothing related to the checkboxes applies to the ProductModel
public class ProductModel
{
public string Title { get; set; }
public IList<SelectListItem> Features { get; set; }
}
This is how I show set the Model for the view
public IActionResult PostAd()
{
var model = new ProductModel
{
Features = new List<SelectListItem>()
{
new SelectListItem { Text = "Camera", Value = "Camera" },
new SelectListItem { Text = "Touch Screen", Value = "Touch Screen" }
}
};
return View(model);
}
How do I properly use checkboxes so that when I post the form, the data comes through to the model?
This is the action that gets fired when posting
[HttpPost]
public IActionResult CreateAd(ProductModel Product)
{
return View("Index");
}
The problem you are having is that when the form is posted, ASP.NET will bind the posted data to your model, but only input values within the form are posted. The reason your SelectListItem has null Text and Value properties is because these values are not being posted in the form. The form would need to contain an input (such as a hidden input) for #Model.Features[i].Text and another for #Model.Features[i].Value for these to be bound back to the SelectListItem during model binding because it is the input's name that binds it to a model property. But keep in mind, receiving these from even hidden inputs would enable a user to change them to any value they want so you would need to validate on the server side that they are 1) valid values and 2) allowed to be selected.
Given that fact, I find it makes more sense to simply reload the list of available options, in your case Features, in your HttpPost action, then update that rebuilt list with the user's submitted selections.
Now the only problem left is you're not even getting Selected set to true. This is again, because it's based on the input's (the checkbox's) value. asp-for="#Model.Features[i].Selected" will give the checkbox the name it needs to bind back to that property, and will bind its value attribute to the value of Selected. However, you then also define your own value attribute as value="#Model.Features[i].Text" which overrides the one that would've been generated by the asp-for helper. So when your form is submitted, the model binder tries to bind "Camera" to the boolean Selected property which can't be done so it just gets it's default false value. Generally, a SelectListItem is used for a dropdown (<select>) input. There's no reason you can't use it for this purpose, but you could also just use your own model type for the checkboxes.
I have a checkbox as follows:
#using (Html.BeginForm("ItemsEdit", "Items", FormMethod.Post))
{
#Html.CheckBox("itemCheck")
}
I want to be able to send an additional value to a controller when it is clicked, similar to something like this:
<input id = "#dataLineItem.Split(Model.ItemList.delimiterChar)[0]" type="checkbox" value="true" name="Remember" onclick="sendCheckId(this.id)" />
Below is the jQuery i am using to pass this id value to my controller:
function sendCheckId(checkedId) {
var sentId = checkedId;
$.post("/Items/ItemsEdit/", { sendIdToAction: sentId })
}
However, if i were to use the method above, i wouldnt know how to pass the 'true/false' values of the checkbox, to the same controller.
Maybe try onclick="sendCheckId(this.id,this.value)"
I'm not sure what that sendCheckId function leads to, but it should be pretty quick and easy to expand it to include the second value.
I found out that i could simply do this using the Razor engine:
#Html.CheckBox("itemCheck", new
{
onclick = "alert('Hello')"
}
Credit: https://www.c-sharpcorner.com/forums/how-to-call-on-click-event-in-mvc-5
(The answer by Ramesh Palanivel)
I'm trying to create paging inside html form.
How do I make each page button change the model's CurrentPage property?
I'm new to MVC, so bear with me please.
I have a list of reports that I need to display in a view named Search. I made a model for that (ReportViewModel), and another model that holds a list of those, named SearchViewModel. In SearchViewModel I have some other variables like SearchName, SearchDate, CurrentPage, PageCount, PageSize, etc. The goal is to do paging and searching in one action named Search in ReportsController.
Now, I would like to keep that action simple by giving that function only SearchViewModel instance as a parameter, so that inside I use all variables of that model. Doing that, I won't have to type parameter names twice (once in SearchViewModel and once as parameters in Search action). I will not need that search function elsewhere, so it's ok for it to not have any parameters other than SearchViewModel instance.
So, very loosely, it looks something like this:
ReportsController.cs
public class ReportsController : Controller
{
public ActionResult Search(SearchViewModel model)
{
if (!ModelState.IsValid)
return View(model);
// do search magic here
return View(model)
}
}
Search.cshtml
#model ISFinReports.Models.SearchViewModel
#{
ViewBag.Title = "List";
Layout = "~/Views/_masterLayout.cshtml";
}
<link href="~/CSS/Search.css" rel="stylesheet" />
<script src="~/Scripts/Search.js"></script>
#using (Html.BeginForm("Search", "Reports", FormMethod.Get))
{
<div id="divSearchBar">
// add #Html.DropDownListFor, #Html.TextBoxFor and submit button here
</div>
<div id="divReportsTable">
<table id="tblReports">
#if (Model.Reports != null)
{
foreach (var r in Model.Reports)
{
// add tr, td of all reports in report list
}
}
</table>
</div>
<div style="text-align:center">
#for (int i = 0; i < Model.PageCount; i++)
{
#Html.ActionLink(i.ToString(), "Search", "Reports", new { CurrentPage = i });
// or
// <input type="submit" value="#i" onClick="meybe something like this?" />
}
Current Page #Html.EditorFor(q => q.CurrentPage), of total #Model.PageCount pages
</div>
}
I know that I can simply type twice all the data I need to flow between controller and view, once in model and once as Search action parameters, but that's extactly what I'm trying not to do. Currently I have a textbox for editing the current page, and it works, because it's created via #Html.EditorFor, but I'd like to have multiple buttons for each page.
I could maybe create a hidden field in that form, and create a javascript function that'll find that hidden field by id, and change it's value, and then call whatever the submit button onClick function is. BUT, is there a better/shorter/more-MVC way to implement that?
I've got a partial view that lists details about my entities. Details include a photo, caption, date, and name. There is an ActionLink for Delete that removes the item from the list.
I would like to make the Caption field an editable textbox to allow the user to edit the contents. Then I wold like to add an 'Update' link that will write this data to the DB. This is the only attribute that can be edited.
Basically I want to avoid the user having to open an 'Edit' form to change this field. I would like to be able to do it from within the list. Not sure how to create the 'Update' ActionLink, send it to the controller, and have the user-entered text available to the controller method.
The model that you pass to the view is of a certain type(of item in db). So, if You change the label with name "Caption" to a textbox of the same name, then the binding would remain the same - the output would be a textbox with the caption taken from the model passed to the View in Controller Action.
As for the update link:
I would create an Action of the same name as the View with [HttpPost] attribute and the model as parameter. The action would be invoked by a submit button in View (so all the labels and the textbox should be enclosed in a form). Inside that action perform the db update.
So:
The View should be something like this:
#model db.Foo
#using (Html.BeginForm()) {
<fieldset>
#Html.LabelFor(model=>model.Name)
(...)
#Html.TextBoxFor(model=>model.Caption)
<input type="submit" value="Update Caption"/>
</fieldset>
}
and the controller actions:
//The action that passes the model to the View
public ActionResult Details()
{
//
//get foo here
//
return View(foo); //Where foo is the item You use for your model
}
[HttpPost]
public ActionResult Details(foo model)
{
//
//Update model here with model of type foo
//
}
Hope this helps
Since it seems to be an extremely basic edit, I would just put the Caption in a Div then using CSS/jQuery display an edit button (glyphicon glyphicon-pencil) on mouseover. On click set the Div to Editable (use styling to show it's in edit mode, and only exit edit mode with a save button). On save, do a jQuery Ajax call to update the value in the database.
Please be extra cautious to not have any SQL Injection Attacks as editable content could contain anything from a user.
CSS might look like:
.editor editor-display button
{
display: none;
}
.editor editor-display:hover .edit-button
{
display: inline-block;
}
.editor editor-edit .edit-button
{
display: none;
}
.editor editor-edit .save-button
{
display: inline-block;
}
Html might look like:
<div class="my-entity editor editor-display" data-id="5" >
<div class="edit-content">#model.Caption</div>
<button id="edit-caption-button" class="edit-button" />
<button id="save-caption-button" class="save-button" />
<div>
Javascript might look like:
$(document).ready(function()
{
$("#save-caption-button").on("click", function()
{
$(this).parent("editor").removeClass("editor-display").addClass("editor-edit");
});
$("#save-caption-button").on("click", function()
{
$.ajax({
url: "/MyEditity/UpdateCaption",
data: { id: $(this).parent(".my-entity").data("id"),
caption: $(this).parent(".my-entity").find(".edit-content").first().text() };
});
$(this).parent("editor").removeClass("editor-edit").addClass("editor-display");
});
});
Controller:
public ActionResult UpdateCaption(int id, string caption)
{
// lookup entity by id
// change caption value
// save
return new EmptyResult();
}
This is a super basic (UNTESTED!) example, with no exception handling.
I have a controller "Contracts" and 3 GET methods: "All", "Focus", which contains grid, and "Edit" for editing, and one POST method: "Edit".
Users can access to Edit from any grid by using button. But after POST executed, i want to redirect them to action that send request.
For example:
open "Focus" grid
select row
clicked edit
make changes, and click save
finally redirect to "Focus" grid (!)
or
open "All" grid
select row
clicked edit
make changes, and click save
finally redirect to "All" grid (!)
public ActionResul All()
{
var items=dbContext.Items;
return View("All",items);
}
in the All View you will have the grid with the data. Selecting a record from the Grid and clicking Edit will take you to the second Action method for Edit.
You may pass a some flag when calling the edit method here. You may add that when you build the edit link like this
#Html.ActionLink("Edit","Edit","Item",new { #id=item.Id, #from="all"},null)
So my Edit will have a querystring key "from" with a value "all"
Same way,in your the View for your Focus, you may pass a different value
#Html.ActionLink("Edit","Edit","Item",new { #id=item.Id, #from="focus"},null)
Now the Edit Action method, You read the parameter and set it as the property value of our edit view model. you may want to add this property to your ViewModel.
public ActionResult Edit(int id,string from)
{
EditItemViewModel item=GetItem(id);
item.From=from;
return View(item);
}
and this View will have the edit form. We will keep the value of From inside a form element so that we can use that on the form post.
#model EditItemViewModel
#using(Html.BeginForm())
{
#Html.HiddenFor(m => m.Id);
#Html.TextBoxFor(m => m.ItemName)
#Html.TextBoxFor(m => m.ItemDesc)
#Html.HiddenFor(m => m.From)
<input type="submit" value="Update" />
}
Where user can edit and submit it again . you handle that in the HttpPost Edit action method. Check the From property value and decide where to redirect after saving
[HttpPost]
public ActionResult Edit(EditItemViewModel model)
{
if(ModelState.IsValid)
{
//Save data
if(model.From=="all")
return RedirectToAction("All");
else
return RedirectToAction("Focus");
}
return View(model);
}
i think that your post edit can be like this
After clicking on the gridrow having (Edit/All/1 or Edit/Focus/2) you can redirect to this
public ActionResult Edit(int id, yourviewmodel viewmodel,string YourFilter)
{
return RedirectToAction(YourFilter);
}
and in global.asax you can set your route like this for the edit submit
routes.MapRoute(
"filters",
"All",
new { controller = "Contracts", action = "All" }
);
routes.MapRoute(
"filters1",
"focus",
new { controller = "Contracts", action = "focus" }
);
for edit click
routes.MapRoute(
"EditFilter",
"Edit/{YourFilter}/{id}",
new { controller = "Contract", action = "Edit",YourFilter = UrlParameter.Optional,id = UrlParameter.Optional }
);