Hidden field value rendering incorrect date to view model - asp.net

PeriodFrom = 05/10/2016
PeriodTo = 06/10/2016
Above properties date format is dd/mm/yyyy as you can see from the below screen shot.
However when i click on the submit button, the values are copied to a view model.
PeriodFrom becomes 10/05/2016 and PeriodTo becomes 10/05/2016
The 10 becomes the day and the 5 becomes the month. Not sure why this is happening. Could someone please advise ?
Startup
var supportCultures = new[]
{
new CultureInfo("en-GB")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en-GB"),
SupportedCultures = supportCultures,
SupportedUICultures = supportCultures
});
View
<form asp-controller="BragManagement" asp-action="Export" method="get" role="form">
<input type="hidden" asp-for="#Model.PeriodFrom" />
<input type="hidden" asp-for="#Model.PeriodTo" />
<input type="hidden" asp-for="#Model.BragValueTitle" />
<button type="submit" class="btn btn-pink">Export</button>
</form>
Method
[HttpGet]
public IActionResult Export(UserVoteDetailSearchViewModel model)
{
var result = _userRepository.GetAllUserVoteDetails(model);
_reportService.GenerateReport(result);
return View();
}
View model
public class UserVoteDetailSearchViewModel
{
public DateTime? PeriodFrom { get; set; }
public DateTime? PeriodTo { get; set; }
public string BragValueTitle { get; set; }
public List<UserVoteDetail> UserVoteDetailList { get; set; }
}

Related

Why when I click next button the form doesn't go to the next page asp.net MVC?

It's supposed to validate and then go to the next view. However, it skips validation entirely and instead reloads the page. I think the issue is with the button itself on the view, I have also tried changing the anchor tag to a submit button, but that just brings me back to the index page. Any help would be appreciated.
My Controller
namespace Trip_Log.Controllers
{
public class TripController : Controller
{
private TripLogContext context { get; set; }
public TripController(TripLogContext ctx) => context = ctx;
public RedirectToActionResult Cancel()
{
TempData.Clear();
return RedirectToAction("Index", "Home");
}
[HttpGet]
public IActionResult Add(string id = "")
{
var vm = new TripViewModel();
if (id == "page2")
{
var accomodation = TempData[nameof(Trip.Accommodation)]?.ToString();
if (string.IsNullOrEmpty(accomodation))
{
vm.PageNumber = 3;
var destination = TempData[nameof(Trip.Destination)].ToString();
vm.Trip = new Trip { Destination = destination };
return View("Add3", vm);
}
else
{
vm.PageNumber = 2;
vm.Trip = new Trip { Accommodation = accomodation };
TempData.Keep(nameof(Trip.Accommodation));
return View("Add2", vm);
}
}
else if (id == "page3")
{
vm.PageNumber = 3;
vm.Trip = new Trip { Destination = TempData.Peek(nameof(Trip.Destination)).ToString() };
return View("Add3", vm);
}
else
{
vm.PageNumber = 1;
return View("Add1", vm);
}
}
[HttpPost]
public IActionResult Add(TripViewModel vm)
{
if(vm.PageNumber == 1)
{
if (ModelState.IsValid)
{
TempData[nameof(Trip.Destination)] = vm.Trip.Destination;
TempData[nameof(Trip.Accommodation)] = vm.Trip.Accommodation;
TempData[nameof(Trip.StartDate)] = vm.Trip.StartDate;
TempData[nameof(Trip.EndDate)] = vm.Trip.EndDate;
return RedirectToAction("Add", new { id = "page2" });
}
else
{
return View("Add1", vm);
}
}
else if(vm.PageNumber == 2)
{
TempData[nameof(Trip.AccommodationPhone)] = vm.Trip.AccommodationPhone;
TempData[nameof(Trip.AccommodationEmail)] = vm.Trip.AccommodationEmail;
return RedirectToAction("Add", new { id = "page3" });
}
else if(vm.PageNumber == 3)
{
vm.Trip.Destination = TempData[nameof(Trip.Destination)].ToString();
vm.Trip.Accommodation = TempData[nameof(Trip.Accommodation)].ToString();
vm.Trip.StartDate = (DateTime)TempData[nameof(Trip.StartDate)];
vm.Trip.EndDate = (DateTime)TempData[nameof(Trip.EndDate)];
vm.Trip.AccommodationPhone = TempData[nameof(Trip.AccommodationPhone)].ToString();
vm.Trip.AccommodationEmail = TempData[nameof(Trip.AccommodationEmail)].ToString();
context.Trips.Add(vm.Trip);
context.SaveChanges();
TempData["message"] = $"Trip to {vm.Trip.Destination} added";
return RedirectToAction("Index", "Home");
}
else
{
return RedirectToAction("Index", "Home");
}
}
}
}
My view
#model TripViewModel
#*
*#
#{
}
<h4>Add Trip Destination and Dates</h4>
<form asp-action="Add" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Trip.Destination">Destination</label>
<input asp-for="Trip.Destination" class="form-control">
<hr />
</div>
<div class="form-group">
<label asp-for="Trip.Accommodation">Accommodation</label>
<input asp-for="Trip.Accommodation" class="form-control">
<hr />
</div>
<div class="form-group">
<label asp-for="Trip.StartDate">Start Date</label>
<input asp-for="Trip.StartDate" class="form-control">
<hr />
</div>
<div class="form-group">
<label asp-for="Trip.EndDate">End Date</label>
<input asp-for="Trip.EndDate" class="form-control">
<hr />
</div>
<a class="btn btn-outline-dark" asp-controller="Trip" asp-action="Add">Next</a>
<a class="btn btn-outline-secondary " asp-controller="Trip" asp-action="Cancel">Cancel</a>
</form>
My model
namespace Trip_Log.Models
{
public class Trip
{
public int TripId { get; set; }
[Required(ErrorMessage = "Please enter a destination")]
public string Destination { get; set; }
[Required(ErrorMessage = "Please enter a start date")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "Please enter an end date")]
public DateTime EndDate { get; set; }
public string Accommodation { get; set; }
public string AccommodationPhone { get; set; }
public string AccommodationEmail { get; set; }
public string ThingToDo1 { get; set; }
public string ThingToDo2 { get; set; }
public string ThingToDo3 { get; set; }
public string ThingsToDo { get { return ThingToDo1 + "\n" + ThingToDo2 + "\n" + ThingToDo3; }
}
}
TripViewModel
public class TripViewModel
{
// Used to shape multiple entities from one or more models into a single object
//
public Trip Trip { get; set; }
public int PageNumber { get; set; }
}
First, seens like you posted the wrong model since in your controller you expected to receive TripViewModel and the model you showed is Trip.
Second, the validation goes to the top of the property, like this:
[Required(ErrorMessage = "Please enter an end date")]
public DateTime EndDate { get; set; }
You can try to replace anchor tag with button like this:
<input type="submit" value="submit" />
And then make sure you load jquery.validate.min.js and jquery.validate.unobtrusive.min.js,then when you click the button,form will be validated and go to action Add.
The reason it didn't work is because I was missing the hidden input field stating the page number.
<input type="hidden" asp-for="PageNumber" />
The next button is also needs to be like so, since as another user pointed out anchors use get.
<button class="btn btn-outline-dark" type="submit">Next</button>
Both the validation and redirects started working with these two changes applied to the View.

Populating data from last row in form when creating a new entry

I have a form to create new data entries for comments. Creating completely new entries works fine. However, when I have already created one entry for my entity I want to populate the data from the last entry in my form.
I have tried to modify the OnGet action to include the data from the last entry. I copied the OnGet code from the Edit view into the Create view. However, if I do this, the Create page is not displayed anymore.
I have the following model:
public class ProjectComment
{
public int Id { get; set; }
public int? ProjectId { get; set; }
public Project Project { get; set; }
public int RAGStatusId { get; set; }
public RAGStatus RAGStatus { get; set; }
public string StatusComment { get; set; }
public string EscalationComment { get; set; }
public string GeneralComment { get; set; }
public double? EOQ { get; set; }
public DateTime LastUpdateDate { get; set; }
public ProjectComment ()
{
this.LastUpdateDate = DateTime.UtcNow;
}
The create form Create.cshtml:
#page
#model SimpleProjectReporting.Pages.ClientDetails.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>ProjectComment</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ProjectComment.ProjectId" class="control-label"></label>
<select asp-for="ProjectComment.ProjectId" class="form-control" asp-items="ViewBag.ProjectId"><option value="" default="" selected="">-- Select --</option></select>
</div>
<div class="form-group">
<label asp-for="ProjectComment.RAGStatusId" class="control-label"></label>
<select asp-for="ProjectComment.RAGStatusId" class="form-control" asp-items="ViewBag.RAGStatusId"><option value="" default="" selected="">-- Select --</option></select>
</div>
<div class="form-group">
<label asp-for="ProjectComment.StatusComment" class="control-label"></label>
<input asp-for="ProjectComment.StatusComment" class="form-control" />
<span asp-validation-for="ProjectComment.StatusComment" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ProjectComment.EOQ" class="control-label"></label>
<input asp-for="ProjectComment.EOQ" class="form-control" />
<span asp-validation-for="ProjectComment.EOQ" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
The original Create.cshtml.cs action:
[BindProperty]
public ProjectComment ProjectComment { get; set; }
public IActionResult OnGet()
{
ViewData["ProjectId"] = new SelectList(_context.Project.Where(a => a.IsArchived == false), "Id", "ProjectName");
ViewData["RAGStatusId"] = new SelectList(_context.RAGStatus.Where(a => a.IsActive == true), "Id", "RAGStatusName");
return Page();
}
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.ProjectComment.Add(ProjectComment);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
The modified Create.cshtml.cs OnGet action:
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
ProjectComment = await _context.ProjectComment
.Include(p => p.Project)
.Include(p => p.RAGStatus).FirstOrDefaultAsync(m => m.Id == id);
if (ProjectComment == null)
{
return NotFound();
}
When modifying the action the way I did it, the page is not displayed anymore (404 error).
I would like to populate the create form with the data from the last entry in the database. If there is no comment, the create page would only populate the name of the project.
You are not sending the "id" parameter to your post action I guess.
So could you please try to adding this line under your form tag:
<form method="post">
<input type="hidden" id="ProjectComment.Id" name="id" value="ProjectComment.Id" />
You are trying to reach the last record of your ProjectComment table.
There are more than one methods to find the last record of your data table. But lets keep it simple.
You have an integer based identity column, which is Auto Increment. So you can simply use below methods to reach out the last created data of your table.
In your OnGetAsync() method:
//maxId will be the maximum value of "Id" columns. Which means that the maximum value is the last recorded value.
int maxId = _context.ProjectComment.Max(i => i.Id);
//And this line will bring you the last recorded "ProjectComment" object.
var projectComment = _context.ProjectComment.Find(maxId);
//You can assign it to your above 'ProjectComment' property if you want to..
ProjectComment = projectComment
Now, since you've find the last recorded data in your database, you can use that object.
Firstly, thanks to Burak for providing the above solution, which works when you want to display the last row in the table. This helped me solving my issue by using the same approach and finding the record based on the Id of the record.
I have amended the code from the Create.cshtml.cs file as follows:
public async Task<IActionResult> OnGetAsync(int? id, int projectid)
{
//This will find the "ProjectComment" object.
var projectComment = _context.ProjectComment.Find(id);
//This will display the 'ProjectComment' on the page
ProjectComment = projectComment;
if (id == null)
{
ProjectComment = projectComment;
ViewData["ProjectId"] = new SelectList(_context.Project, "Id", "ProjectName", projectid);
return Page();
}
ViewData["ProjectId"] = new SelectList(_context.Project, "Id", "ProjectName");
return Page();
}
I am using the int projectid to populate the drop down menu of the project when there is no comment create yet.

Use multiple forms in one view and submit them to several different tables

I have view that in this view, I want to pass some models to it. I'm passing models like this:
#Html.Partial("_Project", Model.AllProjects)
#Html.Partial("_Blog", Model.AllBlog)
#Html.Partial("_Comment", Model.AllComments)
this view feeds on a viewModel (HomeMultiViewModel) that contains some models like this:
public class HomeMultiViewModel
{
public List<Project> AllProjects { get; set; }
public List<Blog> AllBlog { get; set; }
public List<Blog> SearchInBlog { get; set; }
public List<Costumer> AllCostumers { get; set; }
public List<Comments> AllComments { get; set; }
}
Except these, I have 2 forms in this view that the values of one them should be sent to a model named ContactYou, and the values of another one should be send to a model names advise.
This is first form in my view:
<form class="UswithYouForm">
<input type="tel" class="UswithYouFormInput" placeholder="Phone number.." />
<button type="submit" class="UswithYouFormButtom">Submit</button>
</form>
This is the second for in that view:
<form class="adviseForm">
<input type="text" class="form-control" placeholder="Your Name" />
<input type="tel" class="form-control" placeholder="Phone number" />
<input type="text" class="form-control" placeholder="Subject" />
<textarea class="form-control" placeholder="Message..."></textarea>
<button class="slide__text-link">Send your request!</button>
</form>
And at last this is my controller for that view:
namespace Atawin.Controllers
{
public class HomeController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IServiceProvider _serviceProvider;
public HomeController(ApplicationDbContext context, IServiceProvider serviceProvider)
{
_context = context;
_serviceProvider = serviceProvider;
}
public IActionResult Index()
{
HomeMultiViewModel model = new HomeMultiViewModel();
model.AllProjects = (from p in _context.projects select p).ToList();
model.AllBlog = (from b in _context.blogs select b).ToList();
model.AllCostumers = (from c in _context.costumers select c).ToList();
model.AllComments = (from com in _context.comments select com).ToList();
ViewBag.RootPath = "/upload/Norm/";
return View(model);
}
public IActionResult Search(string searchedTxt)
{
HomeMultiViewModel model = new HomeMultiViewModel();
model.AllBlog = (from b in _context.blogs select b).ToList();
model.AllCostumers = (from c in _context.costumers select c).ToList();
model.SearchInBlog = (from sb in _context.blogs where sb.Title.Contains(searchedTxt) orderby sb.Id descending select sb).Take(15).ToList();
ViewBag.RootPath = "/upload/Norm/";
ViewBag.SearchedWords = searchedTxt;
return View(model);
}
// i want an action here to solve my problem
}
}
I actually reed the questions like this on the whole websites, but I can't solve my problem. If you need more to answer this question tell me so I'll send theme to you.

ASP.NET binding partial View droplist

My code is similar to:
class StudentsViewModel:
public class StudentsViewModel
{
public List<Student> Students { get; set; }
public Student SelectedStudent { get; set; }
public string DisplayMode { get; set; }
}
StudentsController:
[HttpPost]
public ActionResult New(int? page, int? SelectedGroup)
{
// some code
StudentsViewModel model = new StudentsViewModel();
model.Students = db.Students.ToList().ToPagedList(pageNumber, pageSize);
model.SelectedStudent = null;
model.DisplayMode = "WriteOnly";
ViewBag.IDGroup = new SelectList(db.Groups, "IDGroup", "Name");
return View("Index", model);
}
View: Index
<form method="post">
<input type="submit" value="Add Student" formaction="/Students/new" class="btn btn-default" />
//some code
#{
if (Model.SelectedStudent != null)
{
if (Model.DisplayMode == "ReadWrite")
{
Html.RenderPartial("_EditStudent", Model.SelectedStudent);
}
}
if (Model.DisplayMode == "WriteOnly")
{
Html.RenderPartial("_InsertStudent", new StudentList.Models.Student());
}
}</form>
Partial View:
_InsertStudent.cshtml
<div class="form-group">
#Html.DropDownList("IDGroup", String.Empty)
#Html.ValidationMessageFor(model => model.IDGroup)
</div>
I have very big problem because my DropDownList doesn't work... Now I display _InsertStudent when I click on button but it doesn't work... If i have
Html.RenderPartial("_InsertStudent", new StudentList.Models.Student());
directly (without button) it works...

How to set a hidden field from a Check box selection in jquery and passing it to the controller action method?

I want to set the Hidden field in jquery for selected checkboxes. A user can select multiple checkboxes. I have multiple checkboxes which I want to save as comma separated value in Database. I am doing this with help of jquery and setting it using hidden field but no luck.
<div id="chkbox">
<input type="checkbox" class="Course" name="Courses" id="CoursesScience" value="Science">Science<br>
<input type="checkbox" class="Course" name="Courses" id="CourseMath" value="Math">Math<br />
<input type="checkbox" class="Course" name="Courses" id="CourseIt" value="IT">IT<br />
<input type="checkbox" class="Course" name="Courses" id="CourseCommerce" value="Commerce">Commerce<br />
<input type="checkbox" class="Course" name="Courses" id="CourseEnglish" value="English">English
</div>
<input type="hidden" name="CoursesSelected" id="CoursesSelected" />
In jquery
var Values = [];
$('.Course').change(function () {
if (this.checked) {
Values.push($(this).val());
}
else{
Values.pop(this);
}
});
$('#CoursesSelected').val(Values).appendTo('form');
This is not working as when I pop the value it pop last instance save in the array but not the one which is being deselected.
1) Also please tell me how I can access the hidden field in a controller.
2) Will this hidden field populate the property Courses in my class.
public partial class Register
{
public int Id { get; set; }
public string Name { get; set; }
public string Class { get; set; }
public string Courses { get; set; }
public string Gender { get; set; }
}
You should not need to use jquery or a hidden field. Instead I would use a view model. Create a new class that only contains the information you want to post from your view, e.g:
public class RegisterViewModel
{
public string Name { get; set; }
public string Class { get; set; }
public string[] Courses { get; set; }
public string Gender { get; set; }
}
I don't know what your controller action looks like, but it should now be something like:
[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
//Map the data posted to the form to your Register class
var student = new Register();
student.Name = model.Name;
student.Class = model.Class;
student.Gender = model.Gender;
if (model.Courses != null)
student.Courses = String.Join(",", model.Courses);
//Then do whatever you need to do to save the data to the database
}
When you post your form, the Courses array should contain an element whose value is the id for each checkbox that has been ticked, e.g. ["CourseMath", "CourseCommerce"].

Resources