Unable to Call a method if i mentioned its attribute as HttpPost - asp.net-mvc

I have a signin page which users can use to signin,i defined its method in controller as HttpPost,when i try to access it from browser,it shows no file found,if i remove the HttpPost attribute it hits the controller and return the view.Eventhough it pass the values in the form to controller if i didnt mentioned its type as HttpPost .Here my code of Login/SignIn.cshtml:
#model BOL.Player_Access
#using (Html.BeginForm("SignIn","Login",FormMethod.Post)){
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Sign In</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.PlayerEmail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PlayerEmail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PlayerEmail, "", 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="SignIn" class="btn btn-default" />
</div>
</div>
</div>
And my LoginController Code is here
[AllowAnonymous] //This filter removes authorize filter for this controller alone and allow anonyomous request
public class LoginController : Controller
{
// GET: Login
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult SignIn(Player_Access plyr_obj)
{
return View();
}
}

You need code for both GET and POST.
You need a GET action to show the form that will be POST'ed
public ActionResult SignIn()
{
return View();
}
This will show the SignIn view.
Then you need a POST action to take the values from the form and send them to the controller.
[HttpPost]
public ActionResult SignIn(Player_Access plyr_obj)
{
//do some work to authenticate the user
return View();
}

Related

How to fix submit form call http method get with query params

I have an asp net core mvc application. An action that create article. The problem is that when I submit the form , my application always calls the get method. How to fix this ?
Create.cshtml
#model MyBlog.Models.Article
#{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
ViewBag.Title = "Create article";
}
<h2>Create article</h2>
#using (Html.BeginForm("Create", "Article", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Content, htmlAttributes: new { #class = "control-label col-md-2" })
<div ass="col-md-10">
#Html.TextAreaFor(model => model.Content,new { #id = "Content", #class = "form-control", #rows = "200" })
#Html.ValidationMessageFor(model => model.Content, "", new { #class = "text-danger" })
<script>
CKEDITOR.replace("Content");
</script>
</div>
</div>
<div class="col-md-offset-2 col-md-10">
<input id="Submit" type="submit" value="submit" />
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Article controller:
// POST: Article
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind("Title,Content")] Article article)
{
try
{
return RedirectToAction("Index");
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View();
}
// GET: Article/Create
[HttpGet]
public ActionResult Create()
{
return View();
}
When I submit form. I see a url like this appears:
xxx//localhost:7158/article/create?Title=a&Content=b__RequestVerificationToken=CfDJ8JLgrvFS_U1JlinCQaKFM9rmomKaF5pDFJjX5Mbp7_OCoQq2hNZ6ygB05XZd-Qy8osia_h_1i1nzXuk5lZWQRBSTsId3hu-lbcapc3xDViukVhv6xeMv_ekiCyW6HdFkFh8iBzjXhJ9bRnZyrnP651U
Debug on VS studio
I have found this bug. If I change Layout shared to null. It working. So I have modified my shared layout. Tks for your help !

The model item passed into the dictionary is of type *** but this dictionary requires a model item of type ***

Hi I want to build a simple url with asp.net MVC to list and edit data from my table.
I got issue at edit page. Can someone help to take a look?
C# is new to me, and I created this by following a youtube tutorial
Error:
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1 [MovieApp.Models.IPR_CompanyGen_200200501]', but this dictionary requires a model item of type 'MovieApp.Models.IPR_CompanyGen_200200501'.
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MovieApp.Models;
namespace MovieApp.Controllers
{
public class HomeController : Controller
{
private dtsdbEntities _db = new dtsdbEntities();
// GET: Home
public ActionResult Index()
{
return View(_db.IPR_CompanyGen_200200501.ToList());
}
// GET: Home/Edit/5
public ActionResult Edit(int id)
{
var CompanyToEdit = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(id.ToString())) select m);
return View(CompanyToEdit);
}
// GET: Home/Edit/5
[HttpPost]
public ActionResult Edit(IPR_CompanyGen_200200501 CompanyToEdit)
{
var OriginalCompany = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(CompanyToEdit.CompanyID.ToString())) select m);
_db.Entry(OriginalCompany).CurrentValues.SetValues(CompanyToEdit);
_db.SaveChanges();
return RedirectToAction("Index");
}
}
internal class MoviesDBEntities
{
}
}
Edit.cshtml
#model MovieApp.Models.IPR_CompanyGen_200200501
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>IPR_CompanyGen_200200501</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.CompanyID)
<div class="form-group">
#Html.LabelFor(model => model.CompanyName, htmlAttributes: new { #class = "control-label
col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CompanyName, new { htmlAttributes = new { #class =
"form-control" } })
#Html.ValidationMessageFor(model => model.CompanyName, "", new { #class = "text-
danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ACCOUNT_ID, htmlAttributes: new { #class = "control-label
col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ACCOUNT_ID, new { htmlAttributes = new { #class =
"form-control" } })
#Html.ValidationMessageFor(model => model.ACCOUNT_ID, "", new { #class = "text-
danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
You forgot to use .First() or .FirstOrDefault().
This is necessary because the LINQ query itself returns a database object System.Data.Entity.Infrastructure.DbQuery hence why we need to save to memory and store to a variable with .First(),.FirstOrDefault(),.ToList(), etc.
public ActionResult Edit(int id)
{
var CompanyToEdit = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(id.ToString())) select m);
// add .FirstOrDefault()
return View(CompanyToEdit.FirstOrDefault());
}

One model for two submit buttons in ASP.NET MVC

I have a form on my view:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DateFrom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateFrom, new { htmlAttributes = new { #class = "form-control date-picker" } })
#Html.ValidationMessageFor(model => model.DateFrom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DateTo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateTo, new { htmlAttributes = new { #class = "form-control date-picker" } })
#Html.ValidationMessageFor(model => model.DateTo, "", 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" formAction=#Url.Action("CreateReport") />
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EMail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EMail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EMail, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Send to email" class="btn btn-default" formAction=#Url.Action("SendEmail") />
</div>
</div>
</div>
}
As you can see I have two butons, first button call CreateReport action and than Send button call SendEmail action. I want to create report and then send this report by e-mail.
Here is my controller actions:
public ActionResult Index()
{
Report
report=ReportRepository.GetReport(DateTime.Parse("02.08.1996"), DateTime.Parse("07.08.1996"));
return View(report);
}
public ActionResult CreateReport(Report report)
{
report = ReportRepository.GetReport(report);
return View("Index", report);
}
public ActionResult SendEmail(Report report)
{
return View("Index", report);
}
And my model class:
public class Report
{
public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; }
public List<OrderDetails> Orders { get; set; }
[Display(Name = "Email address")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string EMail { get; set; }
}
So I mean that I fill Orders list in CreateReport action and display it and after it I press "Send to email" button, that's call "SendEmail" action, where I save Orders list to file and send it.
The problem is that in "SendEmail" action List is null.
How can I fix it?
The simplest way that I could think of is to remove your submit action for create report and handle this with ajax call. So that you will have only one submit action.
Or else you can try with 2 forms in your View.
Personally, I prefer the 1st option.
I'v found a solution. The solution is not to pass model to controller but store my List in Session. Like this:
public ActionResult Index()
{
Report report=ReportRepository.GetReport(DateTime.Parse("02.08.1996"), DateTime.Parse("07.08.1996"));
Session["Orders"] = report.Orders;
return View(report);
}
public ActionResult CreateReport(Report report)
{
report = ReportRepository.GetReport(report);
Session["Orders"] = report.Orders;
return View("Index", report);
}
public ActionResult SendEmail(Report report)
{
List<OrderDetails> orders = (List<OrderDetails>)Session["Orders"];
report.Orders = orders;
return View("Index", report);
}

How to add alert class in viewbag from controller

Here i am trying to add bootstrap alert class to the exception shown in ViewBag.message from controller on clicking the create button. But adding the class shows the exception 'string' does not contain a definition for 'cssClass'.
Below Is Create.cshtml
#model WebApplication8.Models.Info
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<div class="errormsg">
#ViewBag.message
</div>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Info</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.des, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.des, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.des, "", 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>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Below is Create Action Method In controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,name,des")] Info info)
{
try
{
if (ModelState.IsValid)
{
db.create(info);
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
ViewBag.message = ex.Message;
ViewBag.message.cssClass = "alert alert-danger";
return View(info);
}
return View(info);
}
below is Interface Implementer class
public class StudentInfo : IStudentInfo
{
private AbcdEntities db1 = new AbcdEntities();
public void create(Info info)
{
if (info.name!=null)
{
if (info.des!=null)
{
db1.Infoes.Add(info);
db1.SaveChanges();
}
else
{
throw new Exception("Des Cannot Be Empty");
}
}
else
{
throw new Exception("Name Cannot Be Empty");
}
}
ViewBag.message = ex.Message;
You assign to the ViewBag a property message passing to it the Exception.Message, a simple string.
ViewBag.message.cssClass = "alert alert-danger";
Then you try to access a non existent property of a string.
I think you need to understand better the usage of the viewBag, of dynamics, and in wich way MVC propose his way to work on views with Razor.
If you want a complex object in the viewBag you need to create something similar with a dynamic:
ViewBag.Message = new { Text= ex.Message, CssClass = "alert alert-danger" }
and then use it in this way:
<div class="errormsg #ViewBag.Message.CssClass">
#ViewBag.Message.Text
</div>
If it is a recurrent way to represent a return message in a view, you can create a viewModel class to represent the message and create an helper in Razor to enclosure this render rules in a single place.
I've done the following to do what you're looking for using Tempdata.
#*Display any messages returned from other views*#
<div>
#*Error Message*#
#if (TempData["error"] != null)
{
<div class="alert alert-danger">#TempData["error"]</div>
}
</div>
You will need to check your Viewbag.message for null

Use same partial to add form to Create and Edit actions

When you create a new scaffolded item on VS it creates the views for Create and Edit actions that are almost identical, with the exception of the Edit view having an #Html.HiddenFor for your primary key.
Example of Edit view:
#model MyApp.Models.Destaque
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(m => m.IdDestaque)
<div class="form-group">
#Html.LabelFor(model => model.Mensagem, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Mensagem, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Mensagem, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CaminhoImagem, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CaminhoImagem, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CaminhoImagem, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UrlLink, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UrlLink, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UrlLink, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Salvar" class="btn btn-primary" />
</div>
</div>
</div>
}
If I place all content from the BeginForm (including the #using (...) and keep the #Html.HiddenFor(m => m.IdDestaque) in a _Form partial, it doesn't allow me to create new rows.
If I remove the #Html.HiddenFor from the _Form partial, the Edit action does not work (ModelState is invalid).
So what is the right way to do this and keep the DRY principles? Removing the PK from the ModelState validation in my Edit action seems an "uggly" workaround.
You should render the id of your model inside the view and use another overload for Html.BeginForm as follows:
#using (Html.BeginForm("Edit", "Controller", FormMethod.Post, new{attr1 = value1, attr2 = value2}))
{
#Html.HiddenFor(x => x.Id)
...
}
You always make a post to the EditAction. In you controller you will then only need one POST action for Edit and two get actions one Create and other Edit.
public ActionResult Create()
{
return View("Edit"); //return the edit view
}
public ActionResult Edit(int id)
{
var entity = manager.FetchById(id);
if (entity == null)
return HttpNotFound();
//convert your entity to model (optional, but recommended)
var model = Mapper.Map<ViewModel>(entity);
//return your edit view with your model
return View(model);
}
[HttpPost]
public ActionResult Edit(ViewModel model)
{
if (ModelState.IsValid)
{
//work with your model
return RedirectToAction("Index", "Controller");
}
//at this point there is an error, so your must return your view
return View(model);
}
Hope this helps!

Resources