View can't be associated with his controller method - c#

I have the following view:
View:
<fieldset>
<legend>Axa Management System v1.0</legend>
#model InsuranceWebAPI.Models.User
#using (Html.BeginForm("getUserById", "Home", FormMethod.Post))
{
<p>User id:</p>
#Html.TextBoxFor(model => model.Id);
<br>
<button type="submit">Get by id</button>
}
#using (Html.BeginForm("getUserByName", "Home", FormMethod.Post))
{
<p>User name:</p>
#Html.TextBoxFor(model => model.Name);
<br>
<button type="submit">Get by name</button>
}
Associated with this controller:
Controller:
[HttpPost]
private ActionResult getUserByName(string Name)
{
string receivedData;
HttpWebRequest req = (HttpWebRequest)WebRequest
.Create("http://afunnyurl.com");
/*Awesome code*/
return View("Index");
}
But for some reason the view can't access to the method getUserByName() :(
I can access perfectly to the first method, getUserByID() and his controller is:
[HttpPost]
public ActionResult getUserById(string Id)
{
string receivedData;
HttpWebRequest req = (HttpWebRequest)WebRequest
.Create("http://www.anawesomeutl.com");
/*More awesome code*/
return View("Index")
}
I don't understand why I can't access to the second method (getUserByName()) :)
Can anybody help me please?
Thanks in advance!

Currently the visibility of this method is private. You need to change it to public.
[HttpPost]
public ActionResult getUserByName(string Name)
{
// to do : Return something
}
private methods are accessible from withing the containing class/type.

Related

MVC Action not firing

Controller :
public ActionResult Insert()
{
return View();
}
public ActionResult Insert(Employee emp)
{
Employee emp1 = new Employee();
emp1.insert(emp);
return View();
}
cshtml
#using (Html.BeginForm("Employee", "Insert", FormMethod.Post))
{
#Html.TextBoxFor(model => model.name)
#Html.TextBoxFor(model => model.Email)
#Html.TextBoxFor(model => model.mob)
<input type="button" value="Register me" />
}
I have to save my model values on button click ('Register me'). Thanks in advance.
Try to set attributes in your controller:
[HttpGet] // here ([HttpGet] is default so here you can delete this attribute)
public ActionResult Insert()
{
return View();
}
[HttpPost] // here
public ActionResult Insert(Employee emp)
{
Employee emp1 = new Employee();
emp1.insert(emp);
return View();
}
To call some action you need to submit your form. Change your button to submit type:
<input type="submit" value="Register me" /> // type="button" -> type="submit"
Also, in BeginForm you should firstly specify action name and then controller name:
#using (Html.BeginForm("Insert", "Employee", FormMethod.Post))
Its Because you have not declared HTTP POST on INSERT action
[HttpPost]
public ActionResult Insert(Employee emp)
{
Employee emp1 = new Employee();
emp1.insert(emp);
return View();
}
When you are using Beginform and your FormMethod is Post the related Action needs to have same kind of HTTP, By the way it doesn't matter if you have [HttpGet] on first ActionResult Because in MVC, any ActionResult that haven't declared any type of HTTP request/respond are known as [HttpGet]
Also in your BeginForm():
#using (Html.BeginForm("ActionName(Insert)", "ControllerName", FormMethod.Post))
{
#Html.TextBoxFor(model => model.name)
#Html.TextBoxFor(model => model.Email)
#Html.TextBoxFor(model => model.mob)
<input type="submit" value="Register me" />
}

ASP.NET MVC form input not working as expected

Trying to understand why my page doesn't work as expected. I was expecting the SignIn method on the controller to be called when clicking submit button, however, StartGame is still be called instead. The page originates through this URL: http://{domain}/Play/StartGame
Markup:
#{
ViewBag.Title = "Start Game";
}
<h2>StartGame</h2>
#using (Html.BeginForm())
{
#Html.TextBox("gamerId");
<input type="submit" value="SignIn" class="btn btn-default" />
}
Controller:
public class PlayController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult StartGame()
{
return View();
}
public ActionResult SignIn(string gamerId)
{
return View();
}
}
What am I missing here?
You need to specify the action in your BeginForm().
#using (Html.BeginForm("SignIn","Play"))
{
#Html.TextBox("gamerId");
<input type="submit" value="SignIn" class="btn btn-default" />
}
Or another option is to create an overload action and use an attribute:
[HttpPost]
public ActionResult StartGame(string gamerId)
{
return View();
}

How to get textbox value from view to controller in mvc4 on submit button click

How to get the textbox value from view to controller in mvc4?If I using httppost method in controller the page cannot found error was came.
View
#model MVC_2.Models.FormModel
#{
ViewBag.Title = "DisplayForm";
}
#using (Html.BeginForm("DisplayForm", "FormController", FormMethod.Post))
{
<form>
<div>
#Html.LabelFor(model => model.Empname)
#Html.TextBoxFor(model => model.Empname)
#* #Html.Hidden("Emplname", Model.Empname)*#
#Html.LabelFor(model => model.EmpId)
#Html.TextBoxFor(model => model.EmpId)
#* #Html.Hidden("Emplid", Model.EmpId)*#
#Html.LabelFor(model => model.EmpDepartment)
#Html.TextBoxFor(model => model.EmpDepartment)
#* #Html.Hidden("Empldepart", Model.EmpDepartment)*#
<input type="button" id="submitId" value="submit" />
</div>
</form>
}
model
public class FormModel
{
public string _EmpName;
public string _EmpId;
public string _EmpDepartment;
public string Empname
{
get {return _EmpName; }
set { _EmpName = value; }
}
public string EmpId
{
get { return _EmpId;}
set {_EmpId =value;}
}
public string EmpDepartment
{
get { return _EmpDepartment; }
set { _EmpDepartment = value; }
}
}
controller
public ActionResult DisplayForm()
{
FormModel frmmdl = new FormModel();
frmmdl.Empname=**How to get the textbox value here from view on submitbutton click???**
}
First you need to change your button type to "submit". so your form values will be submitted to your Action method.
from:
<input type="button" id="submitId" value="submit" />
to:
<input type="submit" id="submitId" value="submit" />
Second you need to add your model as parameter in your Action method.
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var strname=model.Empname;
return View();
}
Third, If your Controller name is "FormController". you need to change the parameter of your Html.Beginform in your view to this:
#using (Html.BeginForm("DisplayForm", "Form", FormMethod.Post))
{
//your fields
}
P.S.
If your view is the same name as your Action method which is "DisplayForm" you don't need to add any parameter in the Html.BeginForm. just to make it simple. like so:
#using (Html.BeginForm())
{
//your fields
}
Have an ActionResult for the form post:
[HttpPost]
public ActionResult DisplayForm(FormModel formModel)
{
//do stuff with the formModel
frmmdl.Empname = formModel.Empname;
}
Look into Model Binding. Default model binding will take the data embedded in your posted form values and create an object from them.
Let's implement simple ASP.NET MVC subscription form with email textbox.
Model
The data from the form is mapped to this model
public class SubscribeModel
{
[Required]
public string Email { get; set; }
}
View
View name should match controller method name.
#model App.Models.SubscribeModel
#using (Html.BeginForm("Subscribe", "Home", FormMethod.Post))
{
#Html.TextBoxFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
<button type="submit">Subscribe</button>
}
Controller
Controller is responsible for request processing and returning proper response view.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Subscribe(SubscribeModel model)
{
if (ModelState.IsValid)
{
//TODO: SubscribeUser(model.Email);
}
return View("Index", model);
}
}
Here is my project structure. Please notice, "Home" views folder matches HomeController name.
You model will be posted as a object on the action and you can get it in action on post like this:
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
// do whatever needed
string emp = model.EmpName;
}
it you are posting data always put HttpPost attribute on the action.
Your view also has mistakes, make it like this:
#using (Html.BeginForm("DisplayForm", "Form", FormMethod.Post))
{
<div>
#Html.LabelFor(model => model.Empname)
#Html.TextBoxFor(model => model.Empname)
#* #Html.Hidden("Emplname", Model.Empname)*#
#Html.LabelFor(model => model.EmpId)
#Html.TextBoxFor(model => model.EmpId)
#* #Html.Hidden("Emplid", Model.EmpId)*#
#Html.LabelFor(model => model.EmpDepartment)
#Html.TextBoxFor(model => model.EmpDepartment)
#* #Html.Hidden("Empldepart", Model.EmpDepartment)*#
<input type="button" id="submitId" value="submit" />
</div>
}
There are two ways you can do this.
The first uses TryUpdateModel:
public ActionResult DisplayForm()
{
FormModel frmmdl = new FormModel();
TryUpdateModel (frmmdl);
// Your model should now be populated
}
The other, simpler, version is simply to have the model as a parameter on the [HttpPost] version of the action:
[HttpPost]
public ActionResult DisplayForm(FormModel frmmdl)
{
// Your model should now be populated
}
Change your controller like below.
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var Empname = model.Empname;
}
You need to have both Get and Post Methods:
[HttpGet]
public ActionResult DisplayForm()
{
FormModel model=new FormModel();
return View(model);
}
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var employeeName=model.Empname;
return View();
}
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
var value1 = model.EmpName;
}
Model values from hidden field? I recommend the strongly typed approach shown below:
public ActionResult DisplayForm(string Emplname, string Emplid, string Empldepart)
[HttpPost]
public ActionResult DisplayForm(FormModel model)
{
FormModel frmmdl = new FormModel();
frmmdl.Empname=**How to get the textbox value here from view on submitbutton //click???**
}
model.Empname will have the value

Query string param is missed when form validation fail

I have an form with following url:
CreateEntity?officeCodeId=5
When I send form to validate and if validation is fail it returns just CreateEntity url. No officeCodeId=5.
if user click enter on URL or F5 - my site fail - it require missing officecodeId param. I can save it to the session or in the other storage. But I want to have it in the URL
My view:
[HttpGet]
public virtual ActionResult CreateEntity(int? officeCodeId)
{
var model = new CreateViewModel();
FillViewModel(model, officeCodeId);
return View("Create", model);
}
[HttpPost]
protected virtual ActionResult CreateEntity(TEditViewModel model)
{
if (ModelState.IsValid)
{
//Do some model stuff if
}
return View("Create", model);
}
EDIT.
My View:
using (Html.BeginForm("CreateEntity", "Employee", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.HiddenFor(x => x.OfficeCodeId)
<div>
#Html.LabelFor(model => model.FirstName, CommonRes.FirstNameCol)
#Html.TextBoxFor(model => model.FirstName, Model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div>
#Html.LabelFor(model => model.LastName, CommonRes.LastNameCol)
#Html.TextBoxFor(model => model.LastName, Model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div> <div class="input-file-area"></div>
<input id="Agreements" type="file" name="Agreements"/>
</div>
}
Edit 2.
Adding:
#using (Html.BeginForm("CreateEntity", "Employee", FormMethod.Post, new { officeCodeId = Model.OfficeCodeId, enctype = "multipart/form-data" }))
Haven`t help.
It produce the following form:
<form action="/PhoneEmployee/CreateEntity" enctype="multipart/form-data" method="post" officecodeid="5">
Solution Is
<form action="#Url.Action("CreateEntity", "Employee")?officecodeid=#Model.OfficeCodeId" enctype="multipart/form-data" method="post">
The problem is your HttpPost action doesn't have any notion of an id parameter. If you want to support a similar URL then make the action signature support that parameter e.g.
[HttpGet]
public ActionResult CreateEntity(int? officeCodeId)
[HttpPost]
public ActionResult CreateEntity(int officeCodeId, EditViewModel model);
Your actions should looks like this:
Actions:
[HttpGet]
public virtual ActionResult CreateEntity(int? officeCodeId)
{
var model = new CreateViewModel();
FillViewModel(model, officeCodeId);
return View("Create", model);
}
[HttpPost]
public virtual ActionResult CreateEntity(ViewModel model)
{
if (model.IsValid) {
// save...
return RedirectToAction("EditEntity", newId!!!);
}
return View("Create", model);
}
Html:
#using (Html.BeginForm()) {
#Html.HiddenFieldFor(m => Model.officeCodeId)
...
}
Your officeId should be in model. And on html form you can store it in hidden field.
Your final answer is excellent and works great, although you can further enhance it to make it more generic by simply including Request.QueryString:
<form action="#Url.Action("CreateEntity", "Employee")?#(Request.QueryString)"
enctype="multipart/form-data" method="POST">
Then use the POST action:
[HttpPost]
protected virtual ActionResult CreateEntity(TEditViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}

ASP.Net C# How to make a page on website accessible after authenticating via logon

I've been playing with some of the MVC tutorials on making a database website with C# and have a question about how to make a section of the website only accessible ONCE a user has logged in with a username and password.
I have a logon page (code below), which takes the username and password, and then authenticates a user against a database record. Once you've clicked the "login" button the return URL takes you into an Admin section of the website (full path is: http://localhost:53559/Data/update). This bit I'm happy with. However, the issue I have is that the "update" page is still accessible if you've NOT logged in I.e. if I enter in the browser the path above (http://localhost:53559/Data/update) without ever logging in first it will load no problem).
How do I restrict the update page, so it is only available once the user has logged in?
(NB: total beginner, small words please!)
==================================================================================
Controller code for the logon:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using DFAccountancy.Models;
namespace DFAccountancy.Controllers
{
public class AdminController : Controller
{
//
// GET: /Admin/LogOn
public ActionResult LogOn()
{
return View();
}
//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Update", "Data");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// GET: /Account/LogOff
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
==================================================================================
This is the View code for the Update page (which is the Admin section, and should only be accessible once the user has logged in):
#model DFAccountancy.Models.Data
#{
ViewBag.Title = "Update";
}
<h2>Update</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(function () { $("#cl_button1").click(function () { $("#para1").val(""); }); });
$(function () { $("#cl_button2").click(function () { $("#para2").val(""); }); });
</script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Data</legend>
<div class="editor-label">
#Html.LabelFor(model => model.para1)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.para1, new { cols = 75, #rows = 5 })
#Html.ValidationMessageFor(model => model.para1)
<input id="cl_button1" type="button" value="Clear Paragraph" />
</div>
<div class="editor-label">
#Html.LabelFor(model => model.para2)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.para2, new { cols = 75, #rows = 5 })
#Html.ValidationMessageFor(model => model.para2)
<input id="cl_button2" type="button" value="Clear Paragraph" />
</div>
<p>
<input type="submit" value="Update" />
<input type="reset" value="Re-Set to begining" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
==================================================================================
This is the Controller code (DataController) that sits behind the Update View page:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DFAccountancy.Models;
namespace DFAccountancy.Controllers
{
public class DataController : Controller
{
private DataDBContext db = new DataDBContext();
//
// GET: /Data/
public ViewResult Index()
{
return View(db.Data.ToList());
}
//
// GET: /Data/Details/5
public ViewResult Details(string id)
{
Data data = db.Data.Find(id);
return View(data);
}
//
// GET: /Data/Update
public ActionResult Update()
{
var model = db.Data.FirstOrDefault();
return View(model);
}
//
// POST: /Data/Update
[HttpPost]
//[Authorize(Roles = "Administrator")] //Created Validataion so inaccessible from outside
[ValidateInput(false)]
public ActionResult Update(Data data)
{
if (ModelState.IsValid)
{
data.ID = 1; //EF need to know which row to update in the database.
db.Entry(data).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
return View(data);
}
}
}
Use the [Authorize] filter. You can apply it to a controller, or to an individual action.
[Authorize]
public class DataController : Controller
{...
Or
[Authorize]
public ActionResult Update()
{...
As a side note, you are not closing your DB connection from what I can see. Your data context needs to have .Dispose() called on it when it is finished.
EDIT
Moreover, it looks like your get method is not decorated with the authorize, which is why anyone can navigate there. Only the post is decorated, or was until commented out, with the authorize filter. [HttpGet] is used for a basic request, whereas the [HttpPost] generally comes from a form post (Sometimes it is done through ajax).

Categories