I have a problem, where I have a form, and some of the data is not being set in the model and I don't know why or where to look.
My Model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace VolunteerMngSystm.Models
{
public class Organisations
{
public int ID { get; set; }
[Required]
public string Organisation_name { get; set; }
[Required]
public string Industry { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string OrganisationsID { get; set; }
}
}
The Email and OrganisationID are not being set.
My Controller Action method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> OrgReg([Bind("Organisation_name,Industry,Email,OrganisationID")] Organisations organisations)
{
try
{
if (ModelState.IsValid)
{
_context.Add(organisations);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(OrgHome));
}
}
catch (DbUpdateException e)
{
//Log the error (uncomment ex variable name and write a log.
ModelState.AddModelError("" + e, "Unable to save changes. " +
"Try again, and if the problem persists " +
"see your system administrator.");
}
return View(organisations);
}
My View:
#model VolunteerMngSystm.Models.Organisations;
#{
ViewData["Title"] = "Register";
}
<h1>Register</h1>
<h5>As Organisation</h5>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="OrgReg">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Organisation_name" class="control-label">Organisation Name</label>
<input asp-for="Organisation_name" class="form-control" />
<span asp-validation-for="Organisation_name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Industry" class="control-label"></label>
<input asp-for="Industry" class="form-control" />
<span asp-validation-for="Industry" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="OrganisationsID" class="control-label">Verification ID</label>
<input asp-for="OrganisationsID" type="file" accept="image/* " />
<span asp-validation-for="OrganisationsID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Register" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Can anyone please advise me on where to look or how to fix this problem, please?
Since your action need AntiForgeryToken, add it to your form
<form asp-action="OrgReg">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#Html.AntiForgeryToken()
or remove it from the action
also try to remove [Bind] from the action. You have a typo there and you don't need it since you are binding all properties any way.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> OrgReg( Organisations organisations)
Related
After Selecting the file form Choos File, submitting the form showing error "The formFile field is required."
Model is here:
In Debug mode formFile value is set; it shows null;
public class FileUploadTest
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
[NotMapped]
public IFormFile formFile { get; set; }
public string fromFileUrl { get; set; }
}
View is here:
#model UdyogWeb.Models.FileUploadTest
#{
ViewData["Title"] = "Create";
}
<div class="row">
<div class="col-md-4">
<form asp-action="Create" asp-controller="FileUploadTests" enctype="multipart/form-data" method="post">
<div asp-validation-summary="All" class="text-danger" ></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="formFile" class="control-label">Upload File</label>
<input asp-for="formFile" class="form-control" />
<span asp-validation-for="formFile" class="text-danger"></span>
</div>
#* <div class="form-group">
<label asp-for="fromFileUrl" class="control-label"></label>
<input asp-for="fromFileUrl" class="form-control" />
<span asp-validation-for="fromFileUrl" class="text-danger"></span>
</div>*#
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Controller is here:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,fromFileUrl")] FileUploadTest fileUploadTest)
{
string folderurl = " ";
if (ModelState.IsValid)
{
if (fileUploadTest.formFile != null)
{
folderurl = "casefile/brieforwrit/";
folderurl += Guid.NewGuid().ToString() + fileUploadTest.formFile.FileName;
//fileUploadTest.fromFileUrl = folderurl;
string serverfolderurl = Path.Combine(_webHostEnvironment.WebRootPath, folderurl);
using (FileStream fs = new FileStream(serverfolderurl, FileMode.Create))
{
await fileUploadTest.formFile.CopyToAsync(fs);
}
}
fileUploadTest.fromFileUrl = folderurl;
fileUploadTest.Id = Guid.NewGuid();
_context.Add(fileUploadTest);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(fileUploadTest);
}
In this project, I uploaded some files on the Identity Rejor page and it's working perfectly.
Please help to solve this error
Thank you so much for your attention and participation.
In Debug mode formFile value is set; it shows null;
You need to bind your formFile too.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,fromFileUrl,formFile")] FileUploadTest fileUploadTest)
{...}
result:
My HttpPost Edit task is not giving me my list of EventMembers. I put a watch on the GET for my Edit task and it reads my EventMembers just fine. but when i get my POST Edit my EventMembers only shows System.Collections.Generic.List`1[System.String] in my watch window, as well as my input box in my view. Whats happening?
Model:
public class Event
{
[Required]
public int EventId { get; set; }
[ForeignKey("UserId")]
public virtual SchedulerUser SchedulerUser { get; set; }
[MaxLength(50)]
public string EventCreator { get; set; }
public List<string> EventMembers { get; set; }
[Required]
[MaxLength(100)]
public string Subject { get; set; }
[MaxLength(400)]
public string Description { get; set; }
[Required]
public DateTime StartTime { get; set; }
public DateTime? EndTime { get; set; }
[Required]
public bool IsFullDay { get; set; }
[Required]
public bool AcceptOrDecline { get; set; }
}
Controller:
// GET: Events/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var #event = await _context.Events.FindAsync(id);
if (#event == null)
{
return NotFound();
}
return View(#event);
}
// POST: Events/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("EventId,UserId,EventCreator,EventMembers,Subject,Description,StartTime,EndTime,IsFullDay,AcceptOrDecline")] Event #event)
{
if (id != #event.EventId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
#event.SchedulerUser = await _userManager.GetUserAsync(HttpContext.User);
_context.Update(#event);
if (#event.AcceptOrDecline == false)
{
_context.Remove(#event);
}
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!EventExists(#event.EventId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(#event);
}
View:
#model Scheduler.Models.Event
#{
ViewData["Title"] = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Edit</h1>
<h4>Event</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="EventId" />
<div class="form-group">
<label asp-for="Subject" class="control-label"></label>
<input asp-for="Subject" class="form-control" />
<span asp-validation-for="Subject" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EventMembers" class="control-label"></label>
<input asp-for="EventMembers" class="form-control" />
<span asp-validation-for="EventMembers" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StartTime" class="control-label">Start Time</label>
<input asp-for="StartTime" class="form-control" />
<span asp-validation-for="StartTime" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EndTime" class="control-label">End Time</label>
<input asp-for="EndTime" class="form-control" />
<span asp-validation-for="EndTime" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="IsFullDay" /> All Day
</label>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="AcceptOrDecline" /> Accepted
</label>
<p style="color:red; font-weight:bold;">Uncheck this to decline invitation. Event will be removed from your schedule.</p>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Since your EventMembers model property is an Enumerable list, the Html control which represents the property should be indexed.
<div class="form-group">
<label asp-for="EventMembers[0]" class="control-label"></label>
<input asp-for="EventMembers[0]" class="form-control" />
<span asp-validation-for="EventMembers[0]" class="text-danger"></span>
</div>
<div class="form-group">
...
<input asp-for="EventMembers[1]" class="form-control" />
...
</div>
The best practice is to generate the control inside a loop.
#for (int i = 0; i < Model.EventMembers.Count; i++)
{
<div class="form-group">
...
<input asp-for="EventMembers[i]" class="form-control" />
...
</div>
}
First of all forgive me as I am new to MVC.
I have a view which shows server(s) related to a particular application. If none exist, or the user wants to add an additional application/server relationship, they click on "Create New". From this link, I would like the ApplicationID to be passed to the Create view, and the selectlist for Applications to default to the correct Application. Or alternatively, display the application name/id in a label. I would also like to pass the ApplicationId back when "Back to List" is selected.
Model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace ApplicationPortfolio.Models
{
[Table("tblServerApp")]
public class ServerApp
{
public int ServerAppId { get; set; }
public int? ApplicationId { get; set; }
public int? ServerId { get; set; }
public virtual Application Application { get; set; }
public virtual Server Server { get; set; }
}
}
Controller:
// GET: ServerApps/Create
public IActionResult Create(int? id)
{
ViewData["ApplicationId"] = new SelectList(_context.Application, "ApplicationID", "Name", id);
ViewData["ServerId"] = new SelectList(_context.Server, "ServerId", "ServerName");
return View();
}
View:
#model ApplicationPortfolio.Models.ServerApp
#{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Create</h1>
<h4>ServerApp</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<div class="form-group">
<label asp-for="ApplicationId" class="control-label"></label>
<select asp-for="ApplicationId" class="form-control" asp-items="ViewBag.ApplicationId"></select>
</div>
</div>
<div class="form-group">
<label asp-for="ServerId" class="control-label"></label>
<select asp-for="ServerId" class ="form-control" asp-items="ViewBag.ServerId"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
After my test,I found your problem may in your code:
ViewData["ApplicationId"] = new SelectList(_context.Application, "ApplicationID", "Name", id);
ApplicationID and Name should be same with the name in your Application model.
If your model is(example) :
public class Application
{
[Key]
public int ApplicationId { get; set; }
public string ApplicationName { get; set; }
public List<ServerApp> ServerApps { get; set; }
}
Your code should be(Please pay attention to whether the case and match) :
ViewData["ApplicationId"] = new SelectList(_context.Applications, "ApplicationId", "ApplicationName",id);
And if you want to pass the ApplicationId back to Index,you can try following code.
#model ServerApp
#{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h4>ServerApp</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<div class="form-group">
<label asp-for="ApplicationId" class="control-label"></label>
<select id="select" asp-for="ApplicationId" class="form-control" asp-items="ViewBag.ApplicationId"></select>
</div>
</div>
<div class="form-group">
<label asp-for="ServerId" class="control-label"></label>
<select asp-for="ServerId" class="form-control" asp-items="ViewBag.ServerId"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<button id="submit" class="btn btn-info">Back to List</button>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$("#submit").click(function (e) {
e.preventDefault();
var e = document.getElementById("select");
var strUser = e.value;
window.location.href = "/home/index?id=" + strUser;
})
</script>
}
Test Result:
I am creating a web app using asp.net mvc.
I used the default scaffolding to create the controller and the view (I have user table and game table ofc database is created beforehand)
when I try to create new entity in the game table using the default create form it doesn't submit the data.
when I do the same in the user table it works fine.
the problem is that its the default code generated by visual studio and I'm not able to figure out what could be the cause.
this is the controller create action :
// GET: Games/Create
public IActionResult Create()
{
return View();
}
// POST: Games/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Name,ReleaseDate,Genre,ageRestriction,Developer,Description")] Game game)
{
if (ModelState.IsValid)
{
_context.Add(game);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(game);
}
this is the create view :
#model GameSense.Models.Game
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Game</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ageRestriction" class="control-label"></label>
<input asp-for="ageRestriction" class="form-control" />
<span asp-validation-for="ageRestriction" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Developer" class="control-label"></label>
<input asp-for="Developer" class="form-control" />
<span asp-validation-for="Developer" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
and this is the model for "game" :
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace GameSense.Models
{
public class Game
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Required]
public int ageRestriction { get; set; }
[Required]
public string Developer { get; set; }
[Required]
public Coordinates DeveloperLocation { get; set; }
[Required]
public string Description { get; set; }
}
}
as I said, its very "defaulty" i just want to see that everything works before i continue..
any ideas on what might be going on and why i cant create new "Game" items in the database using the default form?
You've set the Coordinates property as Required in your model, but you aren't asking the user to enter any value(s) for that in the form. So it will always be null (and thus always fail validation).
You can either remove the [Required] attribute from the property, or remove the property from the model entirely, or build some UI to allow the field to be populated by the user.
I'm trying to add a "Create" to one of my Controllers (LeagueController), so I created a Create View, which uses my League object.
However, when I go to submit the form, it does not redirect back to the Index view, as I want it to, nor does it enter the log entry to say that I created a league.
League Class
public class League : BaseEntity
{
[Required]
[DataType(DataType.Text)]
public string LeagueName { get; set; }
[Required]
[DataType(DataType.Text)]
public string LeagueInitials { get; set; }
[DataType(DataType.Text)]
public string LeagueURL { get; set; }
[DataType(DataType.DateTime)]
public DateTime Founded { get; set; }
[InverseProperty("League")]
public ICollection<Team> Teams { get; set; }
[ForeignKey("LeagueID")]
public ICollection<LeagueOwners> LeagueOwners { get; set; }
}
LeaguesController Class
public class LeaguesController : Controller
{
private MyDBContext context;
private ILogger logger;
public LeaguesController(MyDBContext context, ILogger logger)
{
this.context = context;
this.logger = logger;
}
public IActionResult Index()
{
this.logger.LogInformation("Reached League Index");
return View();
}
[Route("Create")]
public IActionResult Create()
{
this.logger.LogInformation("Creating a league");
return View();
}
[HttpPost]
public IActionResult Create(League league)
{
this.logger.LogInformation("Create button clicked!");
return this.RedirectToAction("Index");
}
}
Create.cshtml
#model MySite.Core.Entities.League
#{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
<h4>League</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="LeagueName" class="control-label"></label>
<input asp-for="LeagueName" class="form-control" />
<span asp-validation-for="LeagueName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LeagueInitials" class="control-label"></label>
<input asp-for="LeagueInitials" class="form-control" />
<span asp-validation-for="LeagueInitials" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LeagueURL" class="control-label"></label>
<input asp-for="LeagueURL" class="form-control" />
<span asp-validation-for="LeagueURL" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Founded" class="control-label"></label>
<input asp-for="Founded" class="form-control" />
<span asp-validation-for="Founded" class="text-danger"></span>
</div>
<div class="form-group" hidden="hidden">
<label asp-for="Created" class="control-label"></label>
<input asp-for="Created" class="form-control" value="#DateTime.Now" />
<span asp-validation-for="Created" class="text-danger"></span>
</div>
<div class="form-group" hidden="hidden">
<label asp-for="Modified" class="control-label"></label>
<input asp-for="Modified" class="form-control" value="#DateTime.Now" />
<span asp-validation-for="Modified" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
The first way is that you could delete [Route("Create")]which is on your get method.
The second way is that you could add [Route] attribute to your post method like below:
[Route("Create")]
public IActionResult Create()
{
this.logger.LogInformation("Creating a league");
return View();
}
[Route("Create")]
[HttpPost]
public IActionResult Create(League league)
{
this.logger.LogInformation("Create button clicked!");
return this.RedirectToAction("Index");
}
In your form <form asp-action="Create" method="post"> add a tag to point to the correct controller asp-controller="Leagues"
Do not enforce the route, that's just anti-pattern.