How to pass a textbox value to beginform routevalues - asp.net-mvc-4

I have a textbox in my mvc view.I want to pass the textbox data in beginform route values.how to do that?
View:
#using (Html.BeginForm("Index", "InwardDetail", FormMethod.Post))
{
<fieldset style="width:80%;margin-left:auto;margin-right:auto;margin-top:20px;min-width:60%">
<div>
<table class="tableView" style="width:100%">
<tr>
<td>
#Html.DevExpress().Label(lbl=>{
lbl.Name = "lblFromDate";
lbl.Text = "From Date";
}).GetHtml()
</td>
<td>
#Html.TextBox("txtFromDate", value: DateTime.Now.ToString("dd/MM/yyyy"), htmlAttributes: new {id="fromDate", Class="textbox",style="width:70px"})
</td>
<td>
#Html.DevExpress().Button(but=>{
but.Name = "butView";
but.Text = "View";
but.UseSubmitBehavior = true;
}).GetHtml()
</td>
</tr>
<tr>
<td colspan="9">
#Html.Partial("InwardDetailPartial")
</td>
</tr>
</table>
</div>
</fieldset>
}
Controller:
public ActionResult Index(string fDate)
{
_unitOfWork = new UnitOfWork();
blInwarddetail = new InwardRegisterBL(_unitOfWork);
var result = blInwarddetail.GetInwardList(fDate);
return View("Index", result);
}
If I click Button the values should be passed to controller.

Your use of #Html.TextBox("txtFromDate", ..) means you generate an input with name="textFromDate". When you submit a form, the name/value pairs of the forms controls are sent - in your case it would be txtFromDate: 27/06/2015.
But the method your posting to does not have a parameter named txtFromDate (only one named fDate). You need to change the method to
[HttpPost]
public ActionResult Index(string txtFromDate)
{
....
}
However there are numerous issues with your code that you should address
First you should create a view model to represent what your wanting to display/edit in a view
public class FilterViewModel
{
[Display(Name = "...")] // some user friendly display name
[Required(ErrorMesage = "Please enter a valid date")]
public DateTime Date { get; set; }
}
Note from the code you have shown it appears your entering a date, not a string so the property should be DateTime (not string). This also ensures that you get client and server validation for the property. I also give your properties a more descriptive name that fDate (I can't begin to guess what that might mean - maybe FinishDate?)
In the GET method
public ActionResult Index()
{
FilterViewModel model = new FilterViewModel();
model.Date = DateTime.Today;
return View(model);
}
And in the view
#model yourAssembly.FilterViewModel
#using (Html.BeginForm())
{
....
#Html.LabelFor(m => m.Date)
#Html.TextBoxFor(m => m.Date, "{0:dd/MM/yyyy}", new { #class = "textbox" })
#Html.ValidationMessageFor(m => m.Date)
....
}
Note that you are now strongly binding to your model property. The second parameter specifies the format string. There seems no need to override the id property (which will be id="Date"), and to add a class name use #class = "..". Note also since you are adding a class name, you should remove style="width:70px" and instead use css. You should also remove the table elements. Html table elements are used for tabular data, not for layout.
And finally the post method will be
[HttpPost]
public ActionResult Index(FilterViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// model.Date will contain the value enter by the user
}
Finally I would question if this really should be a POST. Form the code, you don't appear to be changing any data and perhaps this should be FormMethod.GET? Or better, use ajax to update the current page based on the filter.

Related

Why is my controller return wrong response data?

I`m using Ajax call to remove items from list. When user clicks on remove button (each button for row with id) it sends Ajax call (Post) to Order/RemoveFromCart. When backend is reached i remove the item from list. Im sure when returning data from controller the item i want to remove is truly removed. The problem is when i take my div and call html(data) from response it removes always the last item in the list.
Thank you for help.
I have tried update dotnet to latest version.
I have tried to remove Ajax call and reload whole view - that fixes the problem but i want to use an Ajax call.
#for (int i = 0; i < Model.CartItems.Count; i++)
{
<input asp-for="CartItems[i].ProductId" type="hidden">
<tr>
<td>
<input type="text" class="inputTextWithoutBorder" readonly="readonly" asp-for="CartItems[i].Product">
</td>
<td>
<select class="select-table" asp-for="#Model.CartItems[i].Packaging" asp-items="#Model.CartItems[i].PackageTypes"></select>
</td>
<td>
<input type="text" class="inputTextWithoutBorder" asp-for="#Model.CartItems[i].Amount" placeholder="Vyberte množství...">
</td>
<td>
<button id="removeFromCartId" onclick="removeFromCart(this);" type="button" value="#i" class="removeButton"></button>
</td>
</tr>
}
[HttpPost]
public IActionResult RemoveFromCart(OrderModel model, int itemToRemove)
{
if (model.CartItems[itemToRemove] != null)
{
model.CartItems.RemoveAt(itemToRemove);
}
return PartialView("_OrderCartWithCalendarPartial", model);
}
Model:
public class CartModel
{
public int ProductId { get; set; }
public int Amount { get; set; }
public string Packaging { get; set; }
public string Product { get; set; }
public List<SelectListItem> PackageTypes { get; } =
new List<SelectListItem>{
new SelectListItem {Value = "", Text = ""},
};
}
Javascript:
function removeFromCart(button) {
var index = button.value;
var placeholderElement = $('#orderFormId');
var myformdata = placeholderElement.serialize()
+ "&itemToRemove=" + index;
var result = $.post("/Order/RemoveFromCart", myformdata);
result.done(function (data) {
$("#cartWithCalendarDiv").html(data);
setDateFieldToZero();
});
}
Problem scenario:
Sending via Ajax list with two items (item0, item1). The controller receives exact list with two items. Remove item0 in controller and return partial view with that updated model. The page reloads only with item0. Why?

How to pass all text of input selected row into action?

i have this view in my project.
I want to get the text of input in each row that is selected.
How to pass all text of input selected row into action
<table width="100%" class="table table-striped table-bordered table-hover" id="dataTables-example">
<thead>
<tr>
<th width="45%">Select</th>
<th width="45%">User Name</th>
<th width="5%">Description</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.TypeList)
{
<tr>
<td>
<input type="checkbox" name=checklist" id="checklist"/>
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
<input type="text" name="Extradecription"/>
</td>
</tr>
}
</tbody>
my Actions. How can I have the corresponding values of text and checkbox for the Selected rows
public IActionResult Index()
{
return View(repository.GetUser());
}
public IActionResult Save(int[] checklist,string[] Extradecription)
{
repository.Save(checklist,Extradecription);
return View(repository.GetUser());
}
If you try to get two different arrays as you have showed in you controller-action code, there will be a trouble with text for non selected items, the array for check boxes will bind as expected but for descriptions will be different, just to be clear, check the following example:
Assuming We have a list with tree options:
100 - Foo
200 - Bar
300 - Zaz
If We set the following selection for items:
Foo, a
Zaz, c
If We take a look on the request, this is the raw request:
checklist = 100,300
Extradecription = a,null,c
So, the trouble is avoid to bind null descriptions for non selected options, this is complicated, in that case I recommend to you a clear solution:
Create a model to create entity process
Create a model for option
Add a list of option model in create entity model
Initialize the model to create a new entity
Render inputs in view using asp-for tag
Retrieve the request to create a new entity
I'll assume the name of models and properties to show how to bind a typed array in your request, change the names according to your scenario.
Create entity model:
public class CreateEntity
{
public CreateEntity()
{
Items = new List<SelectedItem>();
}
// Step 3
[BindProperty]
public List<SelectedItem> Items { get; set; }
// Another properties
}
Model for option:
public class SelectedItem
{
public bool IsSelected { get; set; }
public int Code { get; set; }
public string Name { get; set; }
public string Desc { get; set; }
}
Rendering the options list:
#for (var i = 0; i < Model.Items.Count; i++)
{
<input asp-for="#Model.Items[i].IsSelected" />#Model.Items[i].Name
<input asp-for="#Model.Items[i].Desc" />
<br/>
}
The GET and POST actions in controller:
[HttpGet]
public IActionResult CreateOption()
{
// Set the items list
var model = new CreateEntity
{
Items = new List<SelectedItem>
{
new SelectedItem{ Code = 100, Name = "Foo" },
new SelectedItem{ Code = 200, Name = "Bar" },
new SelectedItem{ Code = 300, Name = "Zaz" }
}
};
return View(model);
}
[HttpPost]
public IActionResult CreateOption(CreateEntity form)
{
// Retrieve only selected items
var query = form.Items.Where(item => item.IsSelected == true).ToList();
return View();
}
If you want to know more about check boxes in Razor pages, please check this link: Checkboxes in a Razor Pages Form
Please let me know if this answer is useful.

Model Value is null in mvc4

I am using a post method, where i am trying to post the value of textbox to database, for this i am doing all the necessary steps, but in that post method my model is null. Find the code below,
My Simple Controller
[HttpPost]
public ActionResult Index(QuestionBankModel question)
{
return View();
}
My Model
public class QuestionBankModel
{
public string question { get; set; }
}
My View
#model OnlinePariksha.Models.QuestionBankModel
#{
var CustomerInfo = (OnlinePariksha.Models.UserLoginModel)Session["UserInfo"];
}
#{
ViewBag.Title = "Index";
}
#{
Layout = "~/Views/Shared/Admin.cshtml";
}
#using (Html.BeginForm("Index", "AdminDashboard", FormMethod.Post))
{
<div id="questionsDiv" style="width:100%; display:none;">
<div style="width:200px">
<table style="width:100%">
<tr>
<td><span><b>Question:</b></span></td>
<td>
#Html.TextBox(Model.question, new Dictionary<string, object> { { "class", "textboxUploadField" } })
</td>
</tr>
</table>
</div>
<div class="clear"></div>
<div>
<input type="submit" class="sucessBtn1" value="Save" />
</div>
</div>
}
Did i miss anything?
Your problem is that the POST method parameter name is the same name as your model property (and as a result model binding fails). Change the method signature to
public ActionResult Index(QuestionBankModel model)
{
...
}
or any other parameter name that is not the same as a model property.
By way of explanation, the DefaultModelBinder first initializes a new instance of QuestionBankModel. It then inspects the form (and other) values and sees question="SomeStringYouEntered". It then searches for a property named question (in order to set its value). The first one it finds is your method parameter so it internally it does QuestionBankModel question = "SomeStringYouEntered"; which fails (you cant assign a strung to a complex object) and the model parameter now becomes null.
Html.TextBox is being used incorrectly because the first parameter is the name of the textbox and you're passing the value of question. I would use this instead:
#Html.TextBoxFor(m => m.question)
Have you tried using #HTML.TextBoxFor?
#Html.TextBoxFor(m=>m.question,new Dictionary<string, object> { { "class", "textboxUploadField" } })

How to pass custom linq query to view

I'm learning and testing how to pass custom linq results
code from controller:
public ActionResult Index()
{
const int pageSize = 5;
return View(from p in db.powners
where p.petowner.StartsWith("")
orderby p.petowner.Skip(0).Take(pageSize).ToList()
select new { p.ownerid, p.petowner, p.ostreet });
}
code from view:
#model System.Collections.Generic.IEnumerable<Mvc4test2.Models.powner>
#{
ViewBag.Title = "Index";
}
<link href="../../Content/PagedList.css" rel="stylesheet" type="text/css" />
<h2>Find owner</h2>
<p>
#using (#Html.BeginForm("index", "lookup", FormMethod.Get))
{
<b>Search</b>#Html.TextBox("search")<input type="submit" value="search" />
}
</p>
<table id="ownertable">
<tr>
<th>
#Html.DisplayNameFor(model => model.petowner)
</th>
<th>
#Html.DisplayNameFor(model => model.ostreet)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ownerid)
</td>
<td>
#Html.DisplayFor(modelItem => item.petowner)
</td>
<td>
#Html.DisplayFor(modelItem => item.ostreet)
</td>
</tr>
}
</table>
What I have tried:
#model IEnumerable<Mvc4test2.Models.powner>
and
#model System.Collections.Generic.IEnumerable<Mvc4test2.Models.powner>
Get following error:
The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery1[<>f__AnonymousType43[System.Int32,System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[Mvc4test2.Models.powner]'.`
Any idea how to pass this query to view and have it work as expected.
Of course later I will use a variable at Skip(0). I have to learn to pass it first.
Thanks
Don't pass anonymous type. Here I suggest you have two options. If Powner class has only 3 fields (ownerid, petowner, ostreet) then select new { p.ownerid, p.petowner, p.ostreet } line in your query is redundant.
public ActionResult Index()
{
const int pageSize = 5;
var model = (from p in db.powners
where p.petowner.StartsWith("")
orderby p.petowner.Skip(0).Take(pageSize) select p).ToList();
return View(model);
}
or if your Powner class is more complicated and your view has to display only ownerid, petowner and ostreet than you should create view model class which contains of these 3 properties only. Example:
public class PownerViewModel
{
public int OwnerId {get;set;} // You should modify these
public string Petowner {get;set;} // properties types
public string OStreet {get;set;} // since I don't exactly know what they are
}
.. and modify your query:
public ActionResult Index()
{
const int pageSize = 5;
var model = from p in db.powners
where p.petowner.StartsWith("")
orderby p.petowner.Skip(0).Take(pageSize)
select new PownerViewModel()
{
OwnerId = p.ownerid,
Petowner = p.petowner,
OStreet = p.ostreet
};
return View(model);
}
.. and of course change model type in your view:
#model System.Collections.Generic.IEnumerable<PownerViewModel>
P.S. There can be some errors or typos since I coded right here.
The problem is with the return type of your query in the Index controller. You should return enumerator of P.
Please check the below link:
passing the correct type from the Controller to the View?

MVC form Post deserialization is incomplete for complex model object

Using MVC 4 Forms, I have a model that always contains four children in a List<T> property. The view displays the model correctly with each of the four child models rendered with a Razor partial view. The problem is that when I submit/post, the model deserializes with a null value for the child list.
Model:
public class MyModel
{
public int SomeValue { get; set; }
public List<ChildModel> Children { get; set; }
...
}
View:
#model MyProject.Models.MyModel
#using (Html.BeginForm())
{
#Html.LabelFor(model => model.SomeValue)
#Html.Partial("ChildPartial", Model.Children[0])
#Html.Partial("ChildPartial", Model.Children[1])
#Html.Partial("ChildPartial", Model.Children[2])
#Html.Partial("ChildPartial", Model.Children[3])
<input type="submit" value="Save" />
}
Controller:
public class MyController : Controller
{
public ActionResult Index()
{
MyModel model = new MyModel();
model.Children = new List<ChildModel>();
model.Children.Add(new ChildModel());
model.Children.Add(new ChildModel());
model.Children.Add(new ChildModel());
model.Children.Add(new ChildModel());
return View(model);
}
[HttpPost]
public ActionResult Index(MyModel model)
{
//model.Children is null here
//do stuff
...
return RedirectToAction("Index", "SomeOtherController");
}
}
The ChildPartial views are each rendering correctly, and I am entering values into the controls, but they are not deserialized into the List<ChildModel>. I can only get the root level properties of MyModel to deserialize in the Post method.
I have tried adding UpdateModel(model); to the beginning of the controller Post method but no luck there. Any ideas?
Edit
ChildModel.cs:
public class ChildModel
{
public String Name { get; set; }
public double Ratio { get; set; }
...
}
ChildPartial.cshtml:
#model MyProject.Models.ChildModel
<div>
<div>
<div>
<span>#Model.Name</span>
</div>
<div>
#Html.LabelFor(m => m.Ratio)
#Html.TextBoxFor(m => m.Ratio, new { autocomplete = "off" })
#Html.ValidationMessageFor(m => m.Ratio)
</div>
</div>
...
</div>
I would first recommend you reading about the specific syntax that the default model binder expects and the naming convention when binding to collections: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Once you compare the names of your input fields with the ones explained in this blog post you will pretty quickly understand why your code doesn't work. You are simply not following the standard naming convention.
In order to fix this I would recommend you using editor templates. So in your main view put the following:
#model MyProject.Models.MyModel
#using (Html.BeginForm())
{
#Html.LabelFor(model => model.SomeValue)
#Html.EditorFor(model => model.Children)
<input type="submit" value="Save" />
}
Then move your ChildPartial.cshtml to ~/Views/Shared/EditorTemplates/ChildModel.cshtml. Notice that the name of the template and the location is extremely important. Make sure you have followed it. And put this inside:
#model MyProject.Models.ChildModel
<div>
<div>
<div>
<span>#Model.Name</span>
</div>
<div>
#Html.LabelFor(m => m.Ratio)
#Html.TextBoxFor(m => m.Ratio, new { autocomplete = "off" })
#Html.ValidationMessageFor(m => m.Ratio)
</div>
</div>
...
</div>
Alright, now run your project, inspect the generated HTML and more specifically the names of the input fields compare them with your initial version and compare them to the blog post I have initially linked to in my answer and you will understand everything about how model binding to collections works in ASP.NET MVC.
Remark: in your child template you don't have a corresponding input field for the Name property of your ChildModel. So don't be surprised if it is null in your controller. You simply never send a value to it when the form is submitted. If you want this to happen you could include it as a hidden field in your editor template:
#Html.HiddenFor(m => m.Name)