Reputation: 33
So i have a view model:
public class ClientViewModel
{
public int ClientID { get; set; }
[Required]
[DisplayName("Client Name")]
public string Name { get; set; }
[Required]
[DisplayName("Client Surname")]
public string Surname { get; set; }
}
And a view where i use this view model(button for searching through the list of clients, button for sorting clients by name and button for sorting clients by surname):
@model IList<ClientViewModel>
@using (Html.BeginForm("Index", "Client", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-md-2">Enter client info:</label>
<div class="col-md-10">
<input type="text" id="clientInfo" name="clientInfo" value="@Session["input"]" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" name="command" value="Search Client" class="btn btn-default" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-2">
<input type="submit" name="command" value="Sort by client name" class="btn btn-default" />
</div>
<div class="col-md-2">
<input type="submit" name="command" value="Sort by client surname" class="btn btn-default" />
</div>
</div>
</div>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model[0].Name)
</th>
<th>
@Html.DisplayNameFor(model => model[0].Surname)
</th>
</tr>
@for (var i = 0; i < Model.Count; i++)
{
@Html.HiddenFor(x => x[i].ClientID)
<tr>
<td>
@Html.HiddenFor(x => x[i].Name)
@Html.DisplayFor(x => x[i].Name)
</td>
<td>
@Html.HiddenFor(x => x[i].Surname)
@Html.DisplayFor(x => x[i].Surname)
</td>
<td>
@Html.ActionLink("Delete Client", "DeleteClient", new { id = Model[i].ClientID }, new { @class = "btn btn-danger" })
</td>
<td>
@Html.ActionLink("Edit Client", "EditClient", new { id = Model[i].ClientID }, new { @class = "btn btn-default" })
</td>
</tr>
}
</table>
}
Let's say the initial clients are:
Name Surname
Adam Gnb
Brandon Cook
Kevin Ginger
Patrick Star
Now when i input "g" in the clientInfo input textbox and click the search button it correctly displays the clients using the keyword i entered. The output is:
Name Surname
Adam Gnb
Kevin Ginger
Now when i click on "Sort by client surname". The desired output is:
Name Surname
Kevin Ginger
Adam Gnb
But the clients parameter in the post method is holding clients "Adam Gnb" and "Brandon Cook" for some reason. That is why the output is:
Name Surname
Brandon Cook
Adam Gnb
It seems that the returning of the IList from the view does not save the clients that are currently showing. Don't really know how to fix this.
Edit 1:
Method for filtering:
public IEnumerable<ClientDTO> GetByClientInfo(string info)
{
if (info.Trim() == "")
throw new ValidationException("Set the input textbox.", "");
var mapper = new MapperConfiguration(cfg => cfg.CreateMap<Client, ClientDTO>()).CreateMapper();
return mapper.Map<IEnumerable<Client>, List<ClientDTO>>(Database.Clients.Find(x => x.Name.ToLower().Contains(info.ToLower()) || x.Surname.ToLower().Contains(info.ToLower())));
}
Method for sorting:
public IEnumerable<ClientDTO> SortBySurname(IEnumerable<ClientDTO> clients)
{
if (clients == null)
throw new ValidationException("The client list is empty", "");
var sortedClients = from client in clients
orderby client.Surname
select client;
return sortedClients;
}
Post method:
[HttpPost]
public ActionResult Index(IList<ClientViewModel> clients, string command, string clientInfo)
{
if(command.Equals("Sort by client name"))
{
var mapper = new MapperConfiguration(cfg => cfg.CreateMap<ClientViewModel, ClientDTO>()).CreateMapper();
var mapperReverse = new MapperConfiguration(cfg => cfg.CreateMap<ClientDTO, ClientViewModel>()).CreateMapper();
var sortedClients = clientService.SortByName(mapper.Map<IList<ClientViewModel>, List<ClientDTO>>(clients));
var afterMap = mapperReverse.Map<IEnumerable<ClientDTO>, IList<ClientViewModel>>(sortedClients);
return View("Index", afterMap);
}
else if(command.Equals("Sort by client surname"))
{
var mapper = new MapperConfiguration(cfg => cfg.CreateMap<ClientViewModel, ClientDTO>()).CreateMapper();
var mapperReverse = new MapperConfiguration(cfg => cfg.CreateMap<ClientDTO, ClientViewModel>()).CreateMapper();
var sortedClients = clientService.SortBySurname(mapper.Map<IList<ClientViewModel>, List<ClientDTO>>(clients));
var afterMap = mapperReverse.Map<IEnumerable<ClientDTO>, IList<ClientViewModel>>(sortedClients);
return View("Index", afterMap);
}
else
{
Session["input"] = clientInfo;
IEnumerable<ClientDTO> clientDtos;
try
{
clientDtos = clientService.GetByClientInfo(clientInfo);
var mapper = new MapperConfiguration(cfg => cfg.CreateMap<ClientDTO, ClientViewModel>()).CreateMapper();
var resultClients = mapper.Map<IEnumerable<ClientDTO>, IList<ClientViewModel>>(clientDtos);
return View("Index", resultClients);
}
catch (ValidationException ex)
{
ViewBag.Error = ex.Message;
if (clients == null)
{
return View(new List<ClientViewModel>());
}
return View("Index", clients);
}
}
}
Upvotes: 3
Views: 76
Reputation: 2691
Look at this link
Try changing your hidden input to not use Html helpers. Cause its binding the post values back to the input control. Instead use plain html elements like following
@for (var i = 0; i < Model.Count; i++)
{
<input type="hidden" name="[@(i)].ClientId" value="@(Model[i].ClientId)" />
<tr>
<td>
<input type="hidden" name="[@(i)].Name" value="@(Model[i].Name)" />
@Html.DisplayFor(x => x[i].Name)
</td>
<td>
<input type="hidden" name="[@(i)].Surname" value="@(Model[i].Surname)" />
@Html.DisplayFor(x => x[i].Surname)
</td>
<td>
@Html.ActionLink("Delete Client", "DeleteClient", new { id = Model[i].ClientID }, new { @class = "btn btn-danger" })
</td>
<td>
@Html.ActionLink("Edit Client", "EditClient", new { id = Model[i].ClientID }, new { @class = "btn btn-default" })
</td>
</tr>
}
Upvotes: 1