I have simple View where I have a ajax form I use for filtering records:
#using (Ajax.BeginForm("Index", new AjaxOptions()
{
InsertionMode=InsertionMode.Replace,
UpdateTargetId="dane"
}))
{
#Html.Partial("SearchTab")
}
#Html.Partial("ShowPartial") // <--- id="dane"
Partial SearchTab:
<div class="row">
<div class="col-lg-3">
<div class="input-group">
<div class="input-group-addon name">
User name:
</div>
<input type="text" name="name" class="form-control" />
</div>
</div>
<div class="col-lg-3">
<div class="input-group">
<div class="input-group-addon surname">
User surname:
</div>
<input type="text" name="surname" class="form-control" />
</div>
</div>
<div class="col-lg-3">
<div class="input-group">
<div class="input-group-addon devicename">
Device name:
</div>
<input type="text" name="deviceName" class="form-control" />
</div>
</div>
<div class="col-lg-3">
<div class="input-group">
<div class="input-group-addon devicemanufacturer">
Device Manufactuer:
</div>
<input type="text" name="deviceManufacturer" class="form-control" />
</div>
</div>
</div>
<input type="submit" class="btn btn-default" value="Filter" id="filter"/>
<br />
Controller action:
public ActionResult Index(string name, string surname ,string deviceName, string deviceManufacturer, string Page)
{
bool RoleId = ad.CheckIfAdmin(Request.LogonUserIdentity.Name.Substring(Request.LogonUserIdentity.Name.LastIndexOf(#"\") + 1));
ViewBag.RoleId = RoleId;
var deviceusages = db.DeviceUsages.Include(d => d.DeviceInstance).Include(d => d.Storage).Include(d => d.User).Where(w=>w.UserId!=6).Skip((int.Parse(Page)-1)*30).Take(30);
if(name!="" && name!=null)
{
deviceusages = deviceusages.Where(w => w.User.Name.Contains(name));
}
if (surname != "" && surname != null)
{
deviceusages = deviceusages.Where(w => w.User.Surname.Contains(surname));
}
if (deviceName != "" && deviceName != null)
{
deviceusages = deviceusages.Where(w => w.DeviceInstance.Device.Name.Contains(deviceName));
}
if (deviceManufacturer!= "" && deviceManufacturer != null)
{
deviceusages = deviceusages.Where(w => w.DeviceInstance.Device.Manufacturer.Contains(deviceManufacturer));
}
return View(deviceusages.ToList());
}
After writing something into input field and pressing filter. Ajax should refresh ShowPartial and keep values in the input fields from SerchTab but instead I get filtered records and inputs are getting empty. Can anyone suggest me edits to change this behaviour
If you are intending to
return View()
you should also return the original model so that control values can be populated with your captured values.
Alternatively if you just need to return the list:
deviceusages.ToList()
Then you can return a PartialView() e.g.;
return PartialView(deviceusages.ToList());
Ok I found cause of a problem.
I need to change this code
<div class="input-group">
<div class="input-group-addon name">
User name:
</div>
<input type="text" name="name" class="form-control" />
</div>
into same thing made wit use of .net Html helpers.
After this change everything works!
#Html.Label("User name: ", new { #class = "input-group-addon" })
#Html.TextBox("name", null, new { #type = "text", #class = "form-control" })
Related
I am trying to make a system where the user can click on an item in a list, and then edit that item while still remaining in the Index-view.
My attempt is just a mix between Index.cshtml and Edit.cshtml:
#model IEnumerable<MyStore.Models.ProductIdentifier>
#{int primary_id = (this.ViewContext.RouteData.Values["primary_id"] != null
? int.Parse(this.ViewContext.RouteData.Values["primary_id"].ToString())
: 0);
}
#foreach (var item in Model)
{
if (item.Id == primary_id)
{
// This list-item is editable (copied from Edit.cshtml):
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="#item.Id" />
<div class="form-group col-lg-4">
<input asp-for="#item.Label" class="form-control" />
<span asp-validation-for="#item.Label" class="text-danger"></span>
</div>
<div class="form-group col-lg-6">
<input asp-for="#item.Description" class="form-control" />
<span asp-validation-for="#item.Description" class="text-danger"></span>
</div>
<div class="form-group col-lg-1">
<input asp-for="#item.SortOrder" class="form-control" />
<span asp-validation-for="#item.SortOrder" class="text-danger"></span>
</div>
<div class="form-group col-lg-1">
<button type="submit" value="Save" class="btn btn-primary">
<span class="glyphicon glyphicon-floppy-disk"></span> Save
</button>
</div>
</form>
}
else
{
// This list-item is just a plain list-item:
<div class="row table">
<div class="col-lg-4">
<a asp-action="Index" asp-route-primary_id="#item.Id">
#Html.DisplayFor(modelItem => item.Label)
</a>
</div>
<div class="col-lg-6">
#Html.DisplayFor(modelItem => item.Description)
</div>
<div class="col-lg-1">
#Html.DisplayFor(modelItem => item.SortOrder)
</div>
<div class="col-lg-1">
<a asp-action="Delete" asp-route-id="#item.Id" class="btn btn-xs btn-danger">
<span class="glyphicon glyphicon-trash"></span>
</a>
</div>
</div>
}
}
The form data is supposed to be posted to the Edit-method in the controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Label,Description,SortOrder")] ProductIdentifier productIdentifier)
{
if (id != productIdentifier.Id) { return NotFound(); }
if (ModelState.IsValid)
{
try
{
_context.Update(productIdentifier);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductIdentifierExists(productIdentifier.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(productIdentifier);
}
... but because I had to add #item. in front of the elements in the form (because the model is an IEnumerable, and I only want to post a single object), the model binding no longer works, and a null object is being posted.
How can I get it to work?
I made it work!
First, I created a ViewModel which contains both an ICollection of identifiers and a single instance of an identifier:
public class ViewModelEditIdentifierInIndexView
{
public ViewModelProductIdentifier SingleItem { get; set; }
public ICollection<ViewModelProductIdentifier> ListOfItems { get; set; }
}
I had to make some changes in the Index method in the controller, to cater for the viewmodel:
public async Task<IActionResult> Index(int? primary_id)
{
ProductIdentifier pi = await _context.ProductIdentifiers
.Where(i => i.Id == primary_id)
.SingleOrDefaultAsync();
ViewModelEditIdentifierInIndexView ViewModel = new ViewModelEditIdentifierInIndexView
{
SingleItem = _mapper.Map<ViewModelProductIdentifier>(pi),
ListOfItems = _mapper.Map<ICollection<ViewModelProductIdentifier>>(await _context.ProductIdentifiers.ToListAsync())
};
return View(ViewModel);
}
Then, I changed the model in the Index-view:
#model MyStore.Models.ViewModels.ViewModelEditIdentifierInIndexView
Then, I changed the edit form. The most important change is the addition of name-tags on each input-field:
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="SingleItem.Id" name="Id" />
<div class="form-group col-lg-4" style="padding-left:0px;">
<input asp-for="SingleItem.Label" name="Label" class="form-control" />
<span asp-validation-for="SingleItem.Label" class="text-danger"></span>
</div>
<div class="form-group col-lg-6" style="padding-left:0px;">
<input asp-for="SingleItem.Description" name="Description" class="form-control" />
<span asp-validation-for="SingleItem.Description" class="text-danger"></span>
</div>
<div class="form-group col-lg-1" style="padding-left:0px;">
<input asp-for="SingleItem.SortOrder" name="SortOrder" class="form-control" />
<span asp-validation-for="SingleItem.SortOrder" class="text-danger"></span>
</div>
<div class="form-group col-lg-1" style="padding-left:0px;">
<button type="submit" value="Save" class="btn btn-xs btn-success">
<span class="glyphicon glyphicon-floppy-disk"></span>
</button>
<a href="/Admin/ProductIdentifiers" class="btn btn-xs btn-warning">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
</div>
</form>
I didn't have to make any changes to the Edit method in the controller.
I don't know what I'm doing bad.
Controller:
public class PictureController : Controller
{
// GET: Picture
public ActionResult Index()
{
return View();
}
public ActionResult AddGroup()
{
ModelPhotoGroup p = new ModelPhotoGroup();
return View(p);
}
[HttpPost]
public ActionResult AddGroup(ModelPhotoGroup p)
{
return View(p);
}
}
In AddGroup of HttpPost I get a p.GroupName = null but I'm writing text in the textbox
View:
#model Boda.WebUI.Models.ModelPhotoGroup
#{
ViewBag.Title = "";
}
<h2>Crear grupo de fotos</h2>
<div class="row">
<div class="col-lg-6 col-lg-offset-3 col-md-6 col-md-offset-3 col-sm-8 col-md-offset-2">
<div class="well">
#using (Html.BeginForm())
{
#Html.HiddenFor(x => x.GroupName)
<div class="form-group">
#Html.LabelFor(x => x.GroupName)
#Html.TextBoxFor(x => x.GroupName, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.GroupName)
</div>
<div class="btn-group">
<input type="submit" value="Guardar" class="btn btn-success" />
#Html.ActionLink("Cancelar y volver a la lista de Fotografias", "Index", null, new
{
#class = "btn btn-default"
})
</div>
}
</div>
</div>
</div>
This is the view. Only I have one TextBoxt to write the name of group
HTML Generated:
<form action="/Picture/AddGroup" method="post"><input id="GroupName" name="GroupName" type="hidden" value=""> <div class="form-group">
<label for="GroupName">GroupName</label>
<input class="form-control" id="GroupName" name="GroupName" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="GroupName" data-valmsg-replace="true"></span>
</div>
<div class="btn-group">
<input type="submit" value="Guardar" class="btn btn-success">
<a class="btn btn-default" href="/Picture">Cancelar y volver a la lista de Fotografias</a>
</div>
You have included
#Html.HiddenFor(x => x.GroupName)
before
#Html.TextBoxFor(x => x.GroupName)
The value of the hidden input will be whatever the default value of GroupName was when you initialized the model (i.e. null)
When you POST, the DefaultModelBinder sets the value of property GroupName to the first value it reads from the form data (that of the hidden input) and ignores any subsequent values with the same name, so the property is always null.
Remove the hidden input and your model will be correctly bound with the value in the textbox.
It's because you did not specify the action and controller,
add the name of action and controller in your form
#using(Html.BeginForm("AddGroup","Picture"))
I have this problem with a viewmodel, when the view is posted I'm getting null values for all the properties.
I've researched a bit, I can see multiple ppl have this problem, I tried some of the solutions but none of them works for me.
This is what I have:
Viewmodel:
public class EventViewModel
{
public projectEvent ProjectEvent { get; set; }
public List<eventType> eventTypes { get; set; }
}
Controller:
[HttpGet]
public ActionResult AddEditEvent(int? id)
{
var eventViewModel = new EventViewModel();
var projectEventModel = new projectEvent();
if (id != null)
{
using (var db = new DBEntities())
{
projectEventModel = (from p in db.projectEvents
where p.eventID == id
select p).FirstOrDefault();
}
}
eventViewModel.ProjectEvent = projectEventModel;
using (var db = new DBEntities())
{
eventViewModel.eventTypes = (from p in db.eventTypes
select p).ToList();
}
return View(eventViewModel);
}
[HttpPost]
public ActionResult AddEditEvent(EventViewModel projectEvent)
{
if (ModelState.IsValid)
{
using (var db = new DBEntities())
{
db.projectEvents.AddOrUpdate(projectEvent);
db.SaveChanges();
}
}
return RedirectToAction("Events");
}
View:
#model TTB.ViewModels.EventViewModel
#{
Layout = "~/Views/Shared/_Layout_Main.cshtml";
}
<h2>Add/Edit Event</h2>
#using (Html.BeginForm("AddEditEvent", "Admin"))
{
<div class="container">
<div class="col-md-8">
<div class="form-group">
<label for="name">Name</label>
#Html.TextBoxFor(m => m.ProjectEvent.eventName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.ProjectEvent.eventName)
</div>
<div class="form-group">
<label for="name">Date</label>
#Html.TextBoxFor(m => m.ProjectEvent.eventDate, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.ProjectEvent.eventDate)
</div>
<div class="form-group">
<label for="name">Event Type</label>
#Html.DropDownListFor(v => v.ProjectEvent.eventType, new SelectList(Model.eventTypes, "eventTypeID", "eventTypeName"), new { #class = "form-control dropdown" })
</div>
#Html.HiddenFor(m => m.ProjectEvent.eventID)
</div>
<div class="col-md-8">
<input type="submit" class="btn btn-success btn-lg btnSaveEdit" value="Save" />
</div>
</div>
}
What am I doing wrong?
Update
Rendered html output:
<form action="/Admin/AddEditEvent" method="post"> <div class="container">
<div class="col-md-8">
<div class="form-group">
<label for="name">Name</label>
<input class="form-control" data-val="true" data-val-required="The eventName field is required." id="ProjectEvent_eventName" name="ProjectEvent.eventName" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="ProjectEvent.eventName" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label for="name">Date</label>
<input class="form-control" data-val="true" data-val-date="The field eventDate must be a date." data-val-required="The eventDate field is required." id="ProjectEvent_eventDate" name="ProjectEvent.eventDate" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="ProjectEvent.eventDate" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label for="name">Event Type</label>
<select class="form-control dropdown" id="ProjectEvent_eventType" name="ProjectEvent.eventType"><option value="1">movie</option>
</select>
</div>
<input data-val="true" data-val-number="The field eventID must be a number." data-val-required="The eventID field is required." id="ProjectEvent_eventID" name="ProjectEvent.eventID" type="hidden" value="0" />
</div>
<div class="col-md-8">
<input type="submit" class="btn btn-success btn-lg btnSaveEdit" value="Save" />
</div>
</div>
</form>
It is because you have a property on your model called projectEvent and you refer to your model as projectEvent when it is passed back into the controller.
Change
public ActionResult AddEditEvent(EventViewModel projectEvent)
To
public ActionResult AddEditEvent(EventViewModel model)
(or another name of your choosing)
http://tech.pro/blog/1930/don-t-name-a-model-the-same-as-a-property-you-re-trying-bind-in-aspnet-mvc
trying to pass 2 values back to the controller id', and 'text'...id passes ok but text always returns nulll any idea why?
<div class="modal-body">
<input type="hidden" id="AlertFreeTextId" name="AlertFreeTextId" value="#Model.AlertFreeTextId" />
<input type="hidden" id="Text" name="Text" value="#Model.Text" />
<div class="form-group">
#Html.LabelFor(x => x.Text)
#Html.TextAreaFor(x => x.Text, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.Text)
</div>
<div>
<a href='#Url.Action("CreateAlertFreeText", "AlertFreeText", new { id = Model.AlertFreeTextId, text = Model.Text})'>
<button class="btn btn-primary">#T("Save")</button>
</a>
</div>
</div>
//controller
public ActionResult CreateAlertFreeText(int id, string text)
{
}
This line here:
<a href='#Url.Action("CreateAlertFreeText", "AlertFreeText", new { id = Model.AlertFreeTextId, text = Model.Text})'>
All this is doing is getting the text that was passed into the View. I assume when you call the view, Model.Text is null, so that's exactly what it's returning.
You need to pull the data from the form when you submit like that.
I'd suggest creating either using a form post, or calling a jquery method to do the post where you can pull the form data.
Maybe something like this: (warning: untested!)
<div class="modal-body">
<input type="hidden" id="AlertFreeTextId" name="AlertFreeTextId" value="#Model.AlertFreeTextId" />
<input type="hidden" id="Text" name="Text" value="#Model.Text" />
<div class="form-group">
#Html.LabelFor(x => x.Text)
#Html.TextAreaFor(x => x.Text, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.Text)
</div>
<div>
<a href='#' id='alertFreeTextLink'>
<button class="btn btn-primary">#T("Save")</button>
</a>
</div>
</div>
<script>
$(document).ready(function() {
$("#alertFreeTextLink").click(function() {
var url = '#Url.Action("CreateAlertFreeText", "AlertFreeText",
new { id = Model.AlertFreeTextId })';
url = url + "&text=" + $("#Text").val();
$.ajax({
url: url
})
.done(function(response) {
/// Do something here
});
});
});
</script>
I have this model, Customer . When i get the information with an id, it works just fine.
Like ;
/Customer/Entity/5
#model ProgSpace.Models.Customer
#{
ViewBag.Title = Model.Name;
Layout = "~/Views/Shared/_MainLayout.cshtml";
}
#section bodypane
{
#using (Html.BeginForm("Entity", "Customer", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="col-md-12">
<div class="col-md-1">
<label>Customer No:</label>
<h4># #(Model.ID) </h4>
</div>
<div class="clearfix"></div><br />
<div class="col-md-2">
<div class="col-md-12">
<div class="col-md-12 fileupload fileupload-exists" data-provides="fileupload">
<div class="fileupload-preview fileupload-exists thumbnail" style="width: 200px; height: 150px;">
<img src="#Model.Picture.Path" />
</div>
<div>
<span class="btn btn-default btn-file">
<span class="fileupload-new">Add Pic </span>
<span class="fileupload-exists">Change</span><input name="file" id="file" type="file">
</span>
Remove
</div>
</div>
</div>
</div>
<div class="col-md-10">
<div class="col-md-3">
<label>Name *</label>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control"})
</div>
<div class="col-md-3">
<label>Company</label>
#Html.TextBoxFor(model => model.Contact.Company, new { #class = "form-control"})
</div>
<div class="col-md-3">
<label>Phone </label>
#Html.TextBoxFor(model => model.Contact.Phone, new { #class = "form-control" })
</div>
</div>
<div class="clearfix"><br /></div>
<p> </p>
<div class="col-md-12">
<div class="btn-group">
<button class="btn btn-danger btn-lg">Cancel</button>
<button type="submit" class="btn btn-success btn-lg">Send</button>
</div>
</div>
</div>
}
}
And in the controller i have these actions.
public ActionResult Entity(int id)
{
Customer cust= sis.Customers.Where(t => t.ID == id).FirstOrDefault();
return View(cust);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Entity(Customer cust, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
/* Do something */
}
else
{
}
return View(cust);
}
When the verb is GET , it's fine. But when i post this form and when the second action (HttpPost action) kicks in , view throws an error..
Object reference not set to an instance of an object
which marks the Model.ID is null in the view.
<div class="col-md-1">
<label>Customer No:</label>
<h4># #(Model.ID) </h4> ---> THIS HERE THROWS NULL EXCEPTION
</div>
I've tried to add a HiddenFor for the Model.ID like
#Html.HiddenFor(t => t.ID)
but it didn't change anything.
How do i get back to the same view with the same context again ?