Displaying a catch exception in MVC - asp.net-mvc

I am quite new to Development in general and MVC.
I am trying to display an exception that is been thrown by my repository, in my MVC site. I have created View : "Error" to handle the error-message.
My main controller look as follows:
using BankMVC.Models;
using BankMVC.WithdrawingService;
using Pocos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace BankMVC.Controllers
{
public class WithdrawingController : Controller
{
WithdrawingServiceClient withdrawingClient;
public WithdrawingController()
{
withdrawingClient = new WithdrawingServiceClient();
}
public ActionResult Withdraw(int Id, int TypeId)
{
BankAccount bankAccount = new BankAccount();
bankAccount.BankAccountId = Id;
bankAccount.BankAccountTypeId = TypeId;
DepositingWithdrawingViewModel withdrawViewModel =
new DepositingWithdrawingViewModel();
withdrawViewModel.BankAccountId = bankAccount.BankAccountId;
withdrawViewModel.Balance = bankAccount.Balance;
withdrawViewModel.BankAccountTypeId = bankAccount.BankAccountTypeId;
return View(withdrawViewModel);
}
[HttpPost]
public ActionResult Withdraw(DepositingWithdrawingViewModel withdrawViewModel)
{
BankAccount bankAccount = new BankAccount();
bankAccount.BankAccountId = withdrawViewModel.BankAccountId;
bankAccount.BankAccountTypeId = withdrawViewModel.BankAccountTypeId;
try
{
withdrawingClient.Withdraw(withdrawViewModel.Amount, bankAccount);
return RedirectToAction("Index", "BankAccount");
}
catch (Exception e)
{
return RedirectToAction("Error", new { message = e.Message });
}
}
}
}
my main controller view looks as follows:
#model BankMVC.Models.DepositingWithdrawingViewModel
#{
ViewBag.Title = "Withdraw";
}
<h2>Withdraw</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Withdraw from Bank Account</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.BankAccountId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BankAccountId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BankAccountId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BankAccountTypeId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BankAccountTypeId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BankAccountTypeId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Balance, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Balance, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Balance, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Amount, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Amount, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Amount, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Withdraw" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index", "BankAccount")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I have created an Error Model which looks as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace BankMVC.Models
{
public class ErrorModel
{
public string Error { get; set; }
}
}
How should my Error-View look Like to display the error-message. It currently looks as follows:
#model BankMVC.Models.ErrorModel
#{
ViewBag.Title = "Error";
}
<h2>Error</h2>
any clarification is appreciated.

I see you are redirecting to an action named "Error" inorder to display your error page. But what i dont see is an action method in the name of "Error". Do the following
Create another method in the controller named "Error"
public ActionResult Error(string message)
{
var model = new ErrorModel();
model.Error = message;
return View(model); // make sure your error view is named as "Error". Else u need to specify the view name in the return command.
}
Please note that I have utilized your Error Model that u have posted .
Also in the Error View, you can utilize the error message by altering your view like this
#model BankMVC.Models.ErrorModel
#{
ViewBag.Title = "Error";
}
<h2>Error</h2>
<h2>Message : #Model.Error</h2>
This will display your error message as well

Related

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());
}

How could I store an "id" (urlparameter.optional) through a textboxfor()

I'm trying to store an id from url in a textboxfor(), but I don't obtain the result. When i put "id" in a textbox, I obtain the correct result. Instead, in a textboxfor(model=> model.IDCantiere,new{#value="id"}). It doesn't run; please help me, I've attached the code fragments:
Controller.cs
// GET: CantiereOres/Create
public ActionResult Create(int id)
{
ViewBag.id = id;
//ViewBag.IdCantiere = new SelectList(db.Cantieres, "IdCantiere", "IdCantiere");
ViewBag.IdPersona = new SelectList(db.CantierePersones, "IdPersona", "Persona");
return View();
}
// POST: CantiereOres/Create
// Per proteggere da attacchi di overposting, abilitare le proprietà a cui eseguire il binding.
// Per ulteriori dettagli, vedere https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "IdOre,IdCantiere,IdPersona,Ore,datetime")] CantiereOre cantiereOre)
{
if (ModelState.IsValid)
{
db.CantiereOres.Add(cantiereOre);
db.SaveChanges();
return RedirectToAction("details", "Cantieres", new { id = cantiereOre.IdCantiere });
}
ViewBag.IdCantiere = new SelectList(db.Cantieres, "IdCantiere", "IdCantiere", cantiereOre.IdCantiere);
ViewBag.IdPersona = new SelectList(db.CantierePersones, "IdPersona", "Persona", cantiereOre.IdPersona);
return View(cantiereOre);
}
View.cshtml:
#model archeagroup.Models.CantiereOre
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.TextBox("id")
<div class="form-horizontal">
<h4>CantiereOre</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.IdCantiere, "IdCantiere", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model=>model.IdCantiere, new {#value ="id", #class = "form-control" } )
#*#Html.EditorFor(model => model.IdCantiere, new { htmlAttributes = new { #class = "form-control" } })*#
#Html.ValidationMessageFor(model => model.IdCantiere, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IdPersona, "IdPersona", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("IdPersona", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.IdPersona, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Ore, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Ore, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Ore, "", 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", "Details", "Cantieres")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
If you want 2441 to be in this textbox right?
#Html.TextBoxFor(model=>model.IdCantiere, new {#value ="id", #class = "form-control" } )
Then in your controller, instead of this:
ViewBag.id = id;
Do this:
Model.IdCantiere = id;
And change your textbox to:
#Html.TextBoxFor(model=>model.IdCantiere, new { #class = "form-control" })
Which will put (from your screenshot) 2441 in the textbox you indicated.
EDIT: So you need to return an instance of archeagroup.Models.CantiereOre from your controller Create method:
public ActionResult Create(int id)
{
var model = new acheagroup.Models.CantiereOre();
model.IdCantiere = id;
model... //other assignments - use this instead of ViewBag
return View(model);
}
With this the above code will work since it will be fed from the model.

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

ViewBag does not work

I'm trying to create an MVC site and I have some trubble with the ViewBag.
It's like it can't contain elements.
I'm using MVC 4.
This is my function in the controller:
public ActionResult Create()
{
ViewBag.DiscID = new SelectList(entities.Disc, "ID", "ID");
ViewBag.StarID = new SelectList(entities.Star, "ID", "Name");
ViewBag.Num = 7;
return View();
}
This is my Create view:
#model Movies.Models.StarAndRole
#{
ViewBag.Title = "Create";
int num;
int.TryParse(ViewBag.Num, out num);
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>StarAndRole</h4>
<h3>num is = #num</h3>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.StarID, "Star", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("StarID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.StarID, "", 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">
#Html.LabelFor(model => model.DiscID, "Disc Num", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("DiscID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.DiscID, "", 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")
}
It appears to me that everything I put in the ViewBag is NULL.
What am i doing wrong?
Thank you in advance!
Int.TryParse method accepts a string (representation of the int value). But you are passing a dynamic type to the method. It should give you an error about that.
If you know you are setting an Int value from your action method, in your view, you can simply read it like
int num = ViewBag.Num;
A better solution is to add the data you want to pass to the view to your view model.
public class YourCreateVm
{
public string Description { set;get;}
public int Num { set;get;}
public List<SelectListItem> Disks { set;get;}
public int SelectedDiskId { set;get;}
}
and in your GET view
public ActionResult Create()
{
var vm = new YourCreateVm { Num = 7 };
vm.Disks = entities.Disc.Select(s=> new SelectListItem
{ Value=s.ID.ToString(), Text =s.Name}).ToList();
return View(vm);
}
and in your view
#model YourCreateVm
#using(Html.BeginForm())
{
<p>My num is : #Model.Num <p>
#Html.TextBoxFor(s=>s.Description)
#Html.DropDownListFor(s=>s.SelectedDiskId, Model.Disks)
<input type="submit" />
}

The current request for action ... on controller type ... is ambiguous between the following action methods

When I run the application on browser with ~/Person/New the result is
The current request for action 'New' on controller type 'PersonController' is ambiguous between the following action method System.Web.Mvc.ActionResult New() on type PersonMVC.Controllers.PersonController System.Web.Mvc.ActionResult New(PersonMVC.Models.Person) on type PersonMVC.Controllers.PersonController
Model
namespace PersonMVC.Models
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
[Required]
[DisplayName("Social Sequrity Number")]
[MinLength(11, ErrorMessage ="Social Security Number Must be 11 digit.")]
[MaxLength(11, ErrorMessage ="")]
public string SocialSecurityNumber { get; set; }
[DisplayFormat(DataFormatString ="{0:dd.MM.yyyy}")]
public DateTime BirthDay { get; set; }
}
}
-View
#model PersonMVC.Models.Person
#{
ViewBag.Title = "New";
}
<h2>New</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Person</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.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SocialSecurityNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SocialSecurityNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SocialSecurityNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BirthDay, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BirthDay, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BirthDay, "", 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")
}
Controller
namespace PersonMVC.Controllers
{
public class PersonController : Controller
{
public ActionResult New()
{
return View();
}
[HttpPost]
public ActionResult New(Person newPerson)
{
bool isTrue = ModelState.IsValid;
return View();
}
}
}
you need to decorate the method with appropriate http verb. Otherwise it will be considered as HttpPost usually.
i think adding [HttpPost] to the controller method would solve the problem

Resources