MVC throwing HTTP 404 error - c#

I am completely stuck and confused why it works with one View to Controller but not the other one.
The one that works:
public class HomeController : Controller
{
// GET: Home
IAuthenticationManager Authentication
{
get { return HttpContext.GetOwinContext().Authentication; }
}
public ActionResult Index()
{
return View();
}
[POST("login")]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel input)
{
if (ModelState.IsValid)
{
if (input.HasValidUsernameAndPassword())
{
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, input.Username),
},
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name, ClaimTypes.Role);
// if you want roles, just add as many as you want here (for loop maybe?)
if (input.isAdministrator)
{
identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
}
else
{
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
}
// tell OWIN the identity provider, optional
// identity.AddClaim(new Claim(IdentityProvider, "Simplest Auth"));
Authentication.SignIn(new AuthenticationProperties
{
IsPersistent = input.RememberMe
}, identity);
return RedirectToAction("password", "authentication");
}
}
return View("show", input);
}
[GET("logout")]
public ActionResult Logout()
{
Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return RedirectToAction("login");
}
}
With this CSHTML code:
#model AgridyneAllIn1MVC.Models.Authentication.LoginModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Details</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Username, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Username)
#Html.ValidationMessageFor(model => model.Username)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RememberMe, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.RememberMe)
#Html.ValidationMessageFor(model => model.RememberMe)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Login" class="btn btn-default" />
</div>
</div>
</div>
}
The CSHTML that doesn't work is:
#using Microsoft.AspNet.Identity
#model AgridyneAllIn1MVC.Models.Authentication.LoginModel
#if(User.Identity.IsAuthenticated)
{
using (Html.BeginForm("resetpassword", "authentication", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Reset your password.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Username, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Username, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Reset" />
</div>
</div>
}
}
The Controller that goes with it is:
public class AuthenticationController : Controller
{
[Authorize]
public ActionResult Password()
{
return View("ResetPassword");
}
[Authorize]
public ActionResult Register()
{
return View("Register");
}
[Authorize]
[POST("resetpassword")]
public ActionResult ResetPassword(LoginModel input)
{
if (ModelState.IsValid)
{
if (User.Identity.IsAuthenticated)
{
if(input.SuccessfullyUpdatedPassword())
{
return View("Password");
}
}
}
return View("Password");
}
[Authorize]
[POST("registernewuser")]
public ActionResult RegisterNewUser(LoginModel input)
{
if (ModelState.IsValid)
{
if (User.Identity.IsAuthenticated)
{
if (input.SuccessfullyUpdatedPassword())
{
return View();
}
}
}
return View();
}
}
Every time I try to get to either of those pages I get
The resource cannot be found. HTTP 404. Requested URL: /resetpassword.
Am I missing something that is required in the HTML.BeginForm() that would make it go to the correct ActionEvent to fire off my code and update the view? This is my first MVC that I am building from scratch and designing the views from scratch. Does MVCs have a problem with having multiple views to one controller? What gets me is that the MVC that works doesn't have anything filled in the HTML.BeginForm(), I tried it without having anything in HTML.BeginForm() and I get the same result. I tried with changing the [GET("resetpassword")] to [GET("")] and it doesn't work either. I have another view that is called register and it has the same problem with the AuthenticationController. So can someone please tell me what is wrong and explain why so I can fully understand how MVC wants things to be done so I get it right for the other 50 plus views that I still have to build yet.

Your Form use FormMethod.Post but there aren't exist POST resetpassword method in your Controller

Change the [GET("resetpassword")] to POST because the form from cshtml file use the post method:
using (Html.BeginForm("resetpassword", "authentication", FormMethod.Post,....

Related

Application crashes when passing ViewModel to the Controller

When I pass the view model to the method it crashes but it works with FormCollection or not passing anything to the onpost method.
[HttpPost]
[AutoValidateAntiforgeryToken]
public ActionResult Update(CustomerInformation model)
{
if (ModelState.IsValid)
{
//save
var UpdateRecord = customerServices.Update(model);
if (UpdateRecord)
{
return RedirectToAction("Details");
}
}
}
#model Customer.Models.CustomerInformationDetails
#using Customer.Models.CustomerInformation
#{
var customerName = Model.Name;
ViewData["Title"] = customerName;
}
<h1>Edit information for #customerName</h1>
<hr />
#using (Html.BeginForm("Update",
"Customer",
FormMethod.Post))
{
<div class="form-group">
#Html.Label("Introduction", "Introduction:", htmlAttributes: new { #class = "control-label col-md-10" })
<div class="col-md-10">
#Html.EditorFor(model => model.Introduction, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.Label("Contact Person", "Contact Person:", htmlAttributes: new { #class = "control-label col-md-10" })
<div class="col-md-10">
#Html.EditorFor(model => model.ContactPerson, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
<input type="submit" value="Update" class="btn btn-primary"></input>
</div>
}
Add
return View(model)
outside of your if statement.
Currently if it fails it has nothing to return.

PopUp not sending data in database in ASP.NET MVC 5 and Entity Framework

The popup code works just fine but after I add the credentials and click on the submit button to create the record nothing happens. I'm new to ASP.NET MVC 5 and Entity Framework 6. Any guidance will be most appreciated.
#model IEnumerable <LogInTest1.Models.Credentials>
#{var createModel = new LogInTest1.Models.Credentials();} #* I think I didn't do this part right *#
#{
ViewBag.Title = "Index";
}
Here is the button code:
<button class="btn btn-default" onclick="AddData()">Click to Create »</button>
<script>
function AddData() {
$("#MyModal").modal();
}
</script>
Here is the popup code:
<div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4>Add Data</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => createModel.userName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => createModel.userName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => createModel.userName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => createModel.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => createModel.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => createModel.password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
Data get easily added in the create view:
<p>
#Html.ActionLink("Create New", "Create")
</p>
Table code:
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.userName)
</th>
<th>
#Html.DisplayNameFor(model => model.password)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.userName)
</td>
<td>
#Html.DisplayFor(modelItem => item.password)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.empId }) |
#Html.ActionLink("Details", "Details", new { id = item.empId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.empId })
</td>
</tr>
}
</table>
Controller code:
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using LogInTest1.Models;
namespace LogInTest1.Controllers
{
public class CredentialsController : Controller
{
private CredentialsContext db = new CredentialsContext();
// GET: Credentials
public ActionResult Index()
{
return View(db.Cr.ToList());
}
// GET: Credentials/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Credentials credentials = db.Cr.Find(id);
if (credentials == null)
{
return HttpNotFound();
}
return View(credentials);
}
// GET: Credentials/Create
public ActionResult Create()
{
return View();
}
// POST: Credentials/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "empId,userName,password")] Credentials credentials)
{
if (ModelState.IsValid)
{
db.Cr.Add(credentials);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(credentials);
}
// GET: Credentials/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Credentials credentials = db.Cr.Find(id);
if (credentials == null)
{
return HttpNotFound();
}
return View(credentials);
}
// POST: Credentials/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "empId,userName,password")] Credentials credentials)
{
if (ModelState.IsValid)
{
db.Entry(credentials).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(credentials);
}
// GET: Credentials/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Credentials credentials = db.Cr.Find(id);
if (credentials == null)
{
return HttpNotFound();
}
return View(credentials);
}
// POST: Credentials/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Credentials credentials = db.Cr.Find(id);
db.Cr.Remove(credentials);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
paste this code into your index page <div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4>Add Data</h4>
</div>
<div class="modal-body">
#{ Html.RenderPartial("~/Views/Credentials/Create.cshtml", new Credentials());}
</div>
</div>
</div>
</div>
<button class="btn btn-default" onclick="AddData()">Click to Create »</button>
<script>
function AddData() {
$("#MyModal").modal();
}
</script>
And your Create page should like this
#model MvcWithDI.Models.Credentials
#using (Html.BeginForm("Create","Credentials",FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Credentials</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.userName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.userName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.userName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}

Html.BeginForm post null model

I have created a create page using asp.net scafolding and below is my page to create expenses.
#model ExpenCare.Models.ExpenseCategory
#{
ViewBag.Title = "CreateExpenseCategories";
}
<div class="row">
#Html.Partial("_RightSidePane")
<div class="col-10 col-sm-8 col-xs-8 col-md-10">
<div class="tab-content" id="nav-tabContent">
<div class="tab-pane fade show active" id="list-Profile-Content" role="tabpanel" aria-labelledby="list-Profile">
#using (Html.BeginForm("CreateExpenseCategories", "Admin", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ExpenseCategory</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Expense, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Expense, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Expense, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
On create this page post data to CreateExpenseCategories method of Admin controller.
public ActionResult CreateExpenseCategories(ExpenseCategory expense)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:1888/api/");
var responseTask = client.PostAsJsonAsync("ExpenseCategories", expense);
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
return RedirectToAction("ExpenseCategories");
}
else
{
ModelState.AddModelError(string.Empty, "Server Error. Please contact administrator.");
}
return View("ExpenseCategories/CreateExpenseCategories", model: expense);
}
The model used to create this page is as below,
namespace ExpenCare.Models
{
public class ExpenseCategory
{
public int Id { get; set; }
[Required]
public string Expense { get; set; }
public string Description { get; set; }
public Company Company { get; set; }
}
}
When I create an expense this always give null exception error and when I debug, the posted data model is null. This must be a small issue for sure, because I have done other create pages in similar way and I did nit encounter any issue. I must be missing a small thing and this might be a stupid question, but I can't find why this gives a null exception error on post.
I think the problem is the usage of Html.EditorFor,
Try this
#Html.TextBoxFor(model => model => model.Expense,new { #class = "form-control" })
or
#Html.EditorFor(model => model.Expense,null,"Expense",new { htmlAttributes = new { #class = "form-control" } } )
Edit problem solved
Property on type ExpenseCategory has the same parameter 'expense'. Change
public ActionResult CreateExpenseCategories(ExpenseCategory expense)
to
public ActionResult CreateExpenseCategories(ExpenseCategory model)
In your model the Id field is not null able Probably you should add an input or hidden input for it to correct model binding:
#Html.HiddenFor(model => model.Id)
Revise:
I test this case and model binding in mvc is working and setting default value for id. Entirely in absence of an input in form model binding in mvc still working. This behavior is sense because all fields by default are optional and we can set required attribute to enforce inputting them.

ASP MVC 5, Route Not Found

Using a mixture of attribute named routing and standard conventional routing.
I have a UserController with two 'Create' actions. One is a HTTPGet for getting the view, and one is a HTTPPost for posting the data back.
Here is that entire controller:
[RoutePrefix("User")]
public class UserController : Controller {
public UserController() {}
[HttpGet]
public ActionResult Create() {
return View();
}
[Route("Create")]
[HttpPost]
public async Task<ActionResult> CreateAsync(UserM m) {
if (!ModelState.IsValid) {
return View(m);
}
var user = new User() {
Email = m.Email,
Forename = m.Forename,
IsActive = true,
Surname = m.Surname
};
return Redirect("");
}
}
However when I try to navigate to User/Create from the submit button on the site, to post the data back, I get a 404.
Here is the route config:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Turn on attribute routing in the controllers
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Here is the view that posts the data back:
#model MyApp.WebMS.Models.UserM
#{
ViewBag.Title = "Create User";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container">
<div class="row">
<div class="xs-12">
<h3>Create User</h3>
<hr class="no-top-margin" />
</div>
</div>
#using (Html.BeginForm()) {
<div class="row">
<div class="col-sm-4">
<h4>Personal Information</h4>
<div class="user-creation-section">
<div class="form-group">
#Html.LabelFor(m => m.Forename, new { #class = "form-label" })
#Html.TextBoxFor(m => m.Forename, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.Surname, new { #class = "form-label" })
#Html.TextBoxFor(m => m.Surname, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "form-label" })
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
</div>
<div class="col-sm-4">
<h4>Job Information</h4>
<div class="user-creation-section">
<div class="form-group">
#Html.LabelFor(m => m.JobTitle, new { #class = "form-label" })
#Html.TextBoxFor(m => m.JobTitle, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.StartDate, new { #class = "form-label" })
#Html.TextBoxFor(m => m.StartDate, new { type = "date", #class = "form-control" })
</div>
</div>
</div>
</div>
<div class="row">
<div class="xs-12 pull-right">
<input type="button" class="btn" value="Back" onclick="location.href='#Url.Action("Index", "Home")'" />
<button type="submit" class="btn btn-primary">Create</button>
</div>
</div>
}
</div>
Since your POST action is named CreateAsync, you'll have to explicitly mention that in your form.
#using (Html.BeginForm("CreateAsync", "User", FormMethod.Post))

ASP .Net MVC Form not calling controller on submit

I am having trouble getting my view to call the post method in my MVC Controller. When I click on the submit button, it does not call the Create method. I add a breakpoint, but it never gets to the code. I am assuming some error, but not sure how to see the error message.
Here is the View:
#model PersonViewModel
#{
ViewBag.Title = "Register";
}
#using (Html.BeginForm(PeopleControllerAction.Create, ControllerName.People, FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal row">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
</div>
<div class="row panel radius">
<div class="medium-2 columns">
<h3>Contact Information</h3>
</div>
<div class="medium-10 columns">
<div class="row">
<div class="medium-6 columns">
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
</div>
</div>
// more fields removed for brevity
<div class="row">
<div class="form-group">
<div>
<input type="submit" value="Submit" class="button" />
</div>
</div>
</div>
}
Here is the controller:
public class PeopleController : Controller
{
private IPersonService context { get; set; }
public PeopleController(IPersonService context)
{
this.context = context;
}
// POST: People/Create
// To protect from overposting attacks, please 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<ActionResult> Create([Bind(Include = "FirstName,LastName,Age,Email,Phone,City,State,HopeToReach,Story,Goal,Image")] PersonViewModel person)
{
if (ModelState.IsValid)
{
try
{
person.ImagePath = ImageUploader.UploadImage(person.Image);
}
catch (ArgumentException e)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Message);
}
var id = await context.AddAsync(person);
return RedirectToAction(PeopleControllerAction.Confirmation);
}
return View(person);
}
}
This was resolved. The action in question did not have a route. I am using attribute routing.

Categories