Server Error in '/' Application in MVC 5 application - asp.net-mvc

I am currently learning MVC 5 by watching video tutorials. I have created one simple customercontroller with two action methods i.e. (AddCustomer and Submit). Here i have created one simple view for AddCustomer and strongly typed view for Showing customer data. When i start application it shows me the customer data entry screen but when i click on submit button i am getting below error.
Can you please tell me what is the issue in my below code?
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Submit
Here's my Customer Controller Code:-
public class CustomerController : Controller
{
// GET: Customer
public ActionResult AddCustomer()
{
return View();
}
public ActionResult Submit(Customer objcust)
{
objcust.CustomerID = Request.Form["txtcustid"];
objcust.CustomerName = Request.Form["txtcustname"];
return View("ShowCustData", objcust);
}
}
Here's My ShowCustData View:-
#model DataAnnotationsEx.Models.Customer
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>ShowCustData</title>
</head>
<body>
<div>
Customer ID: #Model.CustomerID <br />
Customer Name: #Model.CustomerName
</div>
</body>
</html>
Here's My AddCustomer View:-
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>AddCustomer</title>
</head>
<body>
<div>
<form action="Submit" method="post">
Customer ID: <input id="Text1" type="text" name="txtcustid" /><br />
Customer Name: <input id="Text1" type="text" name="txtcustname" /><br />
<input id="Submit1" type="submit" value="submit" />
</form>
</div>
</body>
</html>
Here's My Customer Model:-
public class Customer
{
[Required]
[StringLength(7)]
[RegularExpression("^[A-Z]{3,3}[0-9]{4,4}$")]
public string CustomerID { get; set; }
[Required]
[StringLength(10)]
public string CustomerName { get; set; }
}
Here's My Route.config:-
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Customer", action = "AddCustomer", id = UrlParameter.Optional }
);
}

The problem is your Submit controller action doesn't have [HttpPost] attribute, where your form method defined as POST. You should add the mentioned attribute on corresponding action method:
[HttpPost]
public ActionResult Submit(Customer objcust)
{
objcust.CustomerID = objcust.CustomerID;
objcust.CustomerName = objcust.CustomerName;
return View("ShowCustData", objcust);
}
Note that by default if [HttpPost] attribute not specified, it automatically sets as GET method, hence the action method never be reached by form submit request.
Then, you should replace <form> tag with Html.BeginForm() helper with strongly-typed viewmodel definition like this:
#model Customer
#using (Html.BeginForm("Submit", "Customer", FormMethod.Post))
{
#Html.LabelFor(model => model.CustomerID)
#Html.TextBoxFor(model => model.CustomerID)
#Html.LabelFor(model => model.CustomerName)
#Html.TextBoxFor(model => model.CustomerName)
<input id="Submit1" type="submit" value="submit" />
}
By using strongly-typed viewmodel class, the textboxes are bound automatically to viewmodel properties and be able to retrieve values during form submission.

Related

ASP.NET Core MVC model binding to list returns empty list in POST method? [duplicate]

I have a really wierd issue with MVC.
My models keeps getting submitted empty.
And it's probably really simple, but I just can't find the issue.
My model looks like this:
public class LoginModel
{
public string Username;
public string Password;
}
My controller like this:
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel loginTest)
{
if (loginTest.Username != "x" && loginTest.Password != "y")
{
ModelState.AddModelError("a", "Login failed.");
return View(loginTest);
}
else
{
return RedirectToAction("Home", "Welcome");
}
}
And the view is also very simple, like this.
#model LoginSolution.Models.LoginModel
#{
Layout = null;
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Login</title>
</head>
<body>
#using (Html.BeginForm("Login", "Home"))
{
<div> <span>Username : </span>
#Html.EditorFor(model => model.Username)
<br />
<span>Password : </span>
#Html.EditorFor(model => model.Password)
<br />
#Html.ValidationSummary()
<br />
<input type="submit" value="Login" name="Login" />
</div>
}
</body>
</html>
This is not a question about security or best practice.
This is just a question regarding why the model keeps returning itself as empty upon submitting.
Your model contains fields, not properties (no getter/setter) so the model binder cannot set the values. Change your model to
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}

Update the value in a textbox with controller

In my ASP MVC web application. I have this controller
namespace Test.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index(UserDetails user)
{
user.UserEmail = "Email one";
return View(user);
}
// Post: Home
[HttpPost]
public ActionResult Index(UserDetails user, string command)
{
user.UserEmail = "Email two";
return View(user);
}
#region Helpers
#endregion
}
}
and this view
#model Test.Models.UserDetails
#{ Layout = null;}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.DisplayNameFor(model => model.UserEmail)
#Html.EditorFor(model => model.UserEmail)
<input type="submit" name="Command" value="Search" class="btn btn-default" />
A}
</body>
</html>
When I first run the application it will show “Email one” in the textbox. But when I hit the submit button it will not change the value in the textbox to “Email two”. What I have to change on my code?

MVC4 model binding with two complex models

I have an action on my controller that takes two parameters that should be captured when a form is posted:
[HttpPost]
public ActionResult Index(MyModel model, FormAction action)
The idea is that the model data should be captured in MyModel and the button that the user pressed should be captured in FormAction:
public class MyModel
{
public string MyValue { get; set; }
}
public class FormAction
{
public string Command { get; set; }
}
Here is my view:
#model TestApp.Models.MyModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home"))
{
#Html.TextBoxFor(x => x.MyValue)
<input type="submit" value="OK" name="command" />
<input type="submit" value="Cancel" name="command" />
}
</div>
</body>
</html>
If I add another string parameter to the action called 'command' then the value of the button comes through but it doesn't get bound to the Command property on the FormAction parameter - the parameter is always null.
If I add a Command property to MyModel then the button value does come through.
Is there something in MVC model binding that prevents more than one complex model to be bound in one action method?
The metter is that Html.BeginForm sends only model from top statenent: #model TestApp.Models.MyModel. If I clearly understand what you whant to do, the better solution will be to create ViewModel:
public class ViewModel
{
public MyModel myModel {get; set;}
public FormAction formAction {get; set;}
}
Change View as follows:
#model TestApp.Models.ViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home"))
{
#Html.TextBoxFor(model=> model.myModel.MyValue)
#Html.TextBoxFor(model=> model.formAction.Command)
<input type="submit" value="OK" name="command" />
<input type="submit" value="Cancel" name="command" />
}
</div>
</body>
</html>
And change your Action to:
[HttpPost]
public ActionResult Index(ViewModel model)
I've got to the bottom of this and the reason it wasn't working was simply because the parameter was named action. This is pretty much the equivalent of a keyword in MVC and it is used by the MVC framework to identify the action to be executed.
Changing the parameter name to something else means that the Command property comes through as expected!

When I submit the partial view by either keeping the textbox filled/empty, in both cases full view is loading. How can I call Ajax to post it?

I have Area in MVC3 as mentioned below.
Model
public class AdminModule
{
[Display(Name = "MyName")]
[Required(ErrorMessage = "MyName is missing")]
public String MyName { get; set; }
}
I have Partial View with following code.
#model _1.Areas.Admin.Models.AdminModule
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "myForm" }))
{
#Html.LabelFor(i => i.MyName)
#Html.TextBoxFor(i => i.MyName)
#Html.ValidationMessageFor(i => i.MyName)
<p id="getDateTimeString">
</p>
<input type="submit" value="Click here" id="btn" />
}
View
#model _1.Areas.Admin.Models.AdminModule
#{
ViewBag.Title = "Index";
Layout = "~/Areas/Admin/Views/Shared/_LayoutPage1.cshtml";
}
<h2>
Index</h2>
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript">
</script>
<script type="text/javascript" src="/scripts/jquery.unobtrusive-ajax.js">
</script>
<div id="myForm">
#Html.Partial("_PartialPage1", Model)
</div>
Layout
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
</head>
<body>
<div>
#RenderBody()
</div>
</body>
</html>
Controller Actions
[HttpPost]
public ActionResult Index(AdminModule model)
{
return PartialView(model);
}
[HttpGet]
public ActionResult Index()
{
AdminModule model = new AdminModule();
model.MyName = "My Name";
return View(model);
}
Confusion
When I submit first time.
I get output like below
and form show like this. Question is - Why is index word coming two times?
When I click second time, form appearance remains same and output shows like below.
Question - Why is Jquery coming so many times ?
You could use an Ajax.BeginForm instead of a regular form. But first you should decide which section of your page you want to be updated after the AJAX call.
Let's suppose the following scenario: if the AJAX call is successful you want to update some section of your DOM with some result and if the AJAX fails you want to update the form and display the error message instead.
To implement this you could start by placing the form inside a partial (_MyForm.cshtml):
#model _1.Models.HomeModels
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "myForm" }))
{
#Html.LabelFor(i => i.MyName)
#Html.TextBoxFor(i => i.MyName)
#Html.ValidationMessageFor(i => i.MyName)
<input type="submit" value="Click here" id="btn" />
}
#if (Model.SomeResultProperty != null)
{
<div>#Model.SomeResultProperty</div>
}
and then you could have your main view reference this partial:
#model _1.Models.HomeModels
<div id="myForm">
#Html.Partial("_MyForm", Model)
</div>
The next step is to update your controller action that will handle the AJAX call:
[HttpPost]
public ActionResult Index(HomeModels model)
{
if (ModelState.IsValid)
{
// validation succeeded => we could set the result property
// on the model to be displayed:
model.SomeResultProperty = "this is the result";
}
return PartialView("_MyForm", model);
}
and finally you need to include the jquery.unobtrusive-ajax.js script to your page in order for the Ajax.BeginForm helper to work:
<script type="text/javascript" src="#Url.Content("~/scripts/jquery.unobtrusive-ajax.js")"></script>
Use Ajax.BeginForm instead.
Did you reference validation scripts in your page?

ASP.Net MVC strongly typed partial views and inherited properties

I'm building a web-application with MS MVC 3 and have run into an issue, probably due to a hole in my understanding of model-binding.
Firstly, I have a fairly standard model (irrelevant stuff omitted for brevity, names changed to protect the privacy of innocent objects):
public class ModelBase
{
public int Id { get; set; }
}
public class Order : ModelBase
{
public List<Product> Products { get; set; }
}
public class Product : ModelBase
{
public int OrderId { get; set;}
}
For displaying and editing these, I have a View strongly typed to the Order class, containing a Partial View which is strongly typed to the Product class. The top of the partial view looks like this:
#model Product
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id)
#Html.HiddenFor(model => model.OrderId)
//loads of actual editable properties
I insert the partial into the main view like this:
#Html.Partial("EditorTemplates/Product", Model.Products.First())
...and when the view is rendered in the browser, the "Id" hidden input contains the Id of the Order, not the Id of the Product that I expect and need :(
What am I missing? Can it be fixed without changing the structure of the model and views?
On changing my test project I can confirm that
/Home/Index?id=33
or
/Home/Index/33
DOES overwrite the model value. Can you remove this parameter from the url?
You'd have to change the structure.
You could either put the partial content into the main view, or strongly type the partial to the Order not the Product, or construct the hidden field using Html.Hidden(). MVC is not putting the whole path to the item in the HiddenFor relative to the model in your post action.
ie. In the html you would see
<input type="hidden" name="Id" />
but you really want
<input type="hidden" name="Products[0].Id" />
in order to distinguish the fields and items.
The above problem still remains when you attempt to POST two different hidden inputs with the same name, however I also wrote a test project that works as far as the client.
Hope this helps:
Controller
public ActionResult Index()
{
Order order = new Order() { Id = 1 };
order.Products = new List<Product>() { new Product() { Id = 3, OrderId = 1 } };
return View("Order",order);
}
Models
public class Order : IdentityBase
{
public List<Product> Products { get; set; }
}
public class Product : IdentityBase
{
public int OrderId { get; set; }
}
public class IdentityBase
{
public int Id { get; set; }
}
View
#model MvcApplication1.Models.Order
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Order</title>
</head>
<body>
<div>
#Html.HiddenFor(model => model.Id)
#foreach (MvcApplication1.Models.Product product in Model.Products)
{
<div class="product">
#Html.Partial("Product", product)
</div>
}
</div>
</body>
</html>
Partial View
#model MvcApplication1.Models.Product
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id)
#Html.HiddenFor(model => model.OrderId)
Client Html
<!DOCTYPE html>
<html>
<head>
<title>Order</title>
</head>
<body>
<div>
<input id="Id" name="Id" type="hidden" value="1" />
<div class="product">
<input id="Id" name="Id" type="hidden" value="3" />
<input id="OrderId" name="OrderId" type="hidden" value="1" />
</div>
</div>
</body>

Resources