I have an ASP.NET Core MVC application that has references to two Razor Class Libraries. In each RCL, there is a Model class with the same name (Call it GeneralModel). When the application is ran the following error occurs:
InvalidOperationException: The model item passed into the
ViewDataDictionary is of type 'Namespace1.Models.GeneralModel', but this
ViewDataDictionary instance requires a model item of type
'Namespace2.Models.GeneralModel'.
If I rename one of the Models in one of the RCLs to be unique, the error does not occur and the App preforms as expected.
I produced a bare bones App along with two bare bones RCLs to make sure it wasn't something in our real Solution. The error re-occurred.
Here's the code:
RCL 1 Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TestRCL1.Models;
namespace TestRCL1.Controllers
{
public class TestRCL1Controller : Controller
{
public IActionResult Index()
{
try
{
GeneralModel generalModel = new GeneralModel();
generalModel.fooBar = "fooBar from RCL1";
return PartialView("_GeneralView", generalModel);
}
catch (Exception ex)
{
string s = ex.ToString();
return NotFound();
}
}
}
}
RCL 2 Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TestRCL2.Models;
namespace TestRCL2.Controllers
{
public class TestRCL2Controller : Controller
{
public IActionResult Index()
{
try
{
GeneralModel generalModel = new GeneralModel();
generalModel.fooBar = "fooBar from RCL2";
return PartialView("_GeneralView", generalModel);
}
catch (Exception ex)
{
string s = ex.ToString();
return NotFound();
}
}
}
}
RCL 1 Model:
using System;
using System.Collections.Generic;
using System.Text;
namespace TestRCL1.Models
{
public class GeneralModel
{
public string fooBar { get; set; }
}
}
RCL 2 Model:
using System;
using System.Collections.Generic;
using System.Text;
namespace TestRCL2.Models
{
public class GeneralModel
{
public string fooBar { get; set; }
}
}
RCL 1 View:
#model TestRCL1.Models.GeneralModel
<div>#Model.fooBar</div>
RCL 2 View:
#model TestRCL2.Models.GeneralModel
<div>#Model.fooBar</div>
Main App's Home Controller:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TestRCLApp.Models;
namespace TestRCLApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
Main App's Index.cshtml:
#{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<button id="loadRCL1Content" type="button">Load RCL1 Content</button>
<button id="loadRCL2Content" type="button">Load RCL2 Content</button>
</div>
<script>
$('#loadRCL1Content').click(function (e) {
$.ajax({
url: '/TestRCL1/Index',
type: 'POST'
})
.fail(function (req, status, error) {
alert(error);
})
.done(function (responseData, status, responseObj) {
$('#partialPlaceHolder').html(responseData);
});
});
$('#loadRCL2Content').click(function (e) {
$.ajax({
url: '/TestRCL2/Index',
type: 'POST'
})
.fail(function (req, status, error) {
alert(error);
})
.done(function (responseData, status, responseObj) {
$('#partialPlaceHolder').html(responseData);
});
});
</script>
Test App's Solution Explorer Screen Shot
Has anyone else run into this issue? Do I just need to keep all the Model's uniquely named through out my RCLs or is there a better solution? Thanks in advance!
Your error says it all.
Just because they look the same, doesn't mean they are the same. The compiler is smarter than that and will treat 2 separate classes as 2 separate classes.
Use the same model. or use an interface if you need
Related
I want to use data annotations in my app and the problem is when I click in submit button and don't fill the required field I don't see any error message and it submits. In the controller, the model.state works fine, but I think I should see the error message.
The model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace ValidationTest.Models
{
public class User
{
[Required(ErrorMessage = "Enter your name.")]
public string Name { get; set; }
public string Lastname { get; set; }
}
}
The View:
#model ValidationTest.Models.User
#{
ViewBag.Title = "Index";
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
#using (Html.BeginForm("Record", "Home"))
{
#Html.Label("Name:")
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
<br />
#Html.Label("Lastname:")
#Html.TextBoxFor(m => m.Lastname)
#Html.ValidationMessageFor(m => m.Lastname)
<input type="submit" value="Record" />
}
</body>
</html>
The controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ValidationTest.Models;
namespace ValidationTest.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Record(User usr)
{
if (ModelState.IsValid)
{
return Content("It Worked!");
}
return RedirectToAction("Index");
}
}
}
In Scripts folder inside the ASP.NET MVC project i have:
bootstrap.js
bootstrap.min.js
jquery-3.2.1.intellisense.js
jquery-3.2.1.js
jquery-3.2.1.min.js
jquery-3.2.1.min.map
jquery-3.2.1.slim.js
jquery-3.2.1.slim.min.js
jquery-3.2.1.slim.min.js
modernizr-2.6.2.js
You will have to add JavaScript script references of jquery.validate.min.js and jquery.validate.unobtrusive.min.js for client side validation to work.
Move return RedirectToAction("Index"); inside if (ModelState.IsValid) condition.
return view(); should be added outside if condition.
I have problem pertaining getting string to my controller in asp.net mvc controller. im totally new in angular js with asp.net mvc. can any one help me how to solve the problem. thanks in advance
my controller in asp
using MyProject.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class AngularController : Controller
{
//
// GET: /Angular/
public ActionResult AngularForm()
{
return View();
}
public JsonResult AjaxMethod()
{
string name = "GEORGE";
return Json(name, JsonRequestBehavior.AllowGet);
}
}
}
my script in angular js.
/// <reference path="angular.min.js" />
var myapp = angular.module('myApp', []);
myapp.controller('myController', function ($scope, $http) {
$http.get("/angular/")
.then(function (response) {
$scope.username = response.data;
});
});
my form in html
#{
ViewBag.Title = "AngularForm";
}
<h2>AngularForm</h2>
<div data-ng-app="myApp" data-ng-controller="myController" >
<ul>
<li data-ng-repeat="customer in username">
{{customer.username}}
</li>
</ul>
</div>
<script src="~/Scripts/myScript.js"></script>
This question already has answers here:
The model item passed into the dictionary is of type .. but this dictionary requires a model item of type
(7 answers)
Closed 5 years ago.
I'm using .net core 2.0 (preview2) to build a MVC web app. What I'm trying to do is to have a part of the web page to refresh on a certain interval, so that new data will be loaded.
(For the purpose of this example, it's just the output DateTime.Now)
Here's what I've got so far:
index.cshtml (Main View)
<div id="content">
#Model.name
<br />
#Model.city
<div id="employee">#Html.Partial("Employee")</div>
</div>
<script>
$(document).ready(function () {
var url = "#(Html.Raw(Url.Action("Index", "Employee")))";
$("#employee").load(url);
setInterval(function () {
var url = "#(Html.Raw(Url.Action("ActionName", "Employee")))";
$("#employee").load(url);
}, 1000); //Refreshes every second
$.ajaxSetup({ cache: false }); //Turn off caching
});
</script>
HomeController.cs (Controller1)
using System;
using Microsoft.AspNetCore.Mvc;
using DemoApp.Models;
namespace DemoApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
CustomersViewModel customers = new CustomersViewModel();
customers.name = "John";
customers.city = "New York";
return View(customers);
}
}
}
CustomerViewModel.cs (Model 1)
using System;
namespace DemoApp.Models
{
public class CustomersViewModel
{
public string name { get; set; }
public string city { get; set; }
}
}
Employee.cshtml (Partial view)
#model EmployeeViewModel
<div id="employeeContent">
Hello Employees!
<br />
#Model.employeeName
<br />
#Model.employeeCity
<br />
#Model.time
</div>
EmployeeViewModel.cs (Model 2)
using System;
namespace DemoApp.Models
{
public class EmployeeViewModel
{
public string employeeName { get; set; }
public string employeeCity { get; set; }
public string time { get; set; }
}
}
EmployeeController.cs (Controller2)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using DemoApp.Models;
namespace DemoApp.Controllers
{
public class EmployeeController : Controller
{
public IActionResult Index()
{
EmployeeViewModel evm = new EmployeeViewModel();
evm.employeeName = "Jack";
evm.employeeCity = "Los Angeles";
evm.time = DateTime.Now.ToString();
return View();
}
}
}
As you can see, I'm trying to show data from the logic in Index() from the EmployeeController inside the partial view. To check if it works, the current date/time should be showed.
With this state, I get the error:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'DemoApp.Models.CustomersViewModel', but this ViewDataDictionary instance requires a model item of type 'DemoApp.Models.EmployeeViewModel'.
I tried a lot of different things I found here, but actually nothing really helped. Sure, I avoided the error message, but then I wasn't able to load any data into the partial view.
Where do I go from here, what am I missing?
EDIT: This is not an exact duplicate at all. The duplicate link refers to something in MVC, but not in .net core MVC, where #Html.Action doesn't exist.
But the link did help :-)
You need to change your EmployeeController:
public class EmployeeController : Controller
{
public PartialViewResultIndex()
{
EmployeeViewModel evm = new EmployeeViewModel();
evm.employeeName = "Jack";
evm.employeeCity = "Los Angeles";
evm.time = DateTime.Now.ToString();
return PartialView("Employee", evm);
}
}
I have:
GuestResponseRepository, IRepository -> Interface, HomeController -> Controlle, Thanks -> View
The GuestReresponseRepository has a list with responses in it. When I add a response via a form the response is added to the list. When you try to add a response for the second time with the same values the AddReponse method returns false. I want to use the bool in my view to display a different text. How can I do this? Below my code
GuestResponseRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PartyInvites.Abstract;
namespace PartyInvites.Models
{
public class GuestResponseRepository : IRepository
{
private static List<GuestResponse> responses = new List<GuestResponse>();
IEnumerable<GuestResponse> IRepository.GetAllResponses()
{
return responses;
}
bool IRepository.AddResponse(GuestResponse response)
{
if (responses.Any(x => x.Email == response.Email)) //here
{
if (responses.Any(x => x.WillAttend == response.WillAttend)) //here
{
return false;
}
var attend = responses.First(x => x.Email == response.Email && x.WillAttend != response.WillAttend);
attend.WillAttend = response.WillAttend;
return true;
}
responses.Add(response);
return true;
}
}
}
IRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PartyInvites.Models;
namespace PartyInvites.Abstract
{
public interface IRepository
{
IEnumerable<GuestResponse> GetAllResponses();
bool AddResponse(GuestResponse response);
}
}
Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PartyInvites.Models;
using PartyInvites.Abstract;
namespace PartyInvites.Controllers {
public class HomeController : Controller {
private IRepository repository;
public HomeController(IRepository iRepository)
{
this.repository = iRepository;
}
public ViewResult Index() {
return View(repository.GetAllResponses());
}
public ViewResult PartyPeople()
{
return View(repository.GetAllResponses());
}
[HttpGet]
public ViewResult RsvpForm() {
return View();
}
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse) {
if (ModelState.IsValid) {
repository.AddResponse(guestResponse);
return View("Thanks", guestResponse);
}
else
{
// there is a validation error
return View();
}
}
}
}
view
#model PartyInvites.Models.GuestResponse
#{
ViewBag.Title = "Thanks";
}
<div class="text-center">
<h1>Thank you, #Model.Name!</h1>
<div class="lead">
#if (Model.WillAttend == true) {
#:It's great that you're coming. The drinks are already in the fridge!
} else {
#:Sorry to hear that you can't make it, but thanks for letting us know.
}
#if (bool from Addresponse is false) {
#:<p>You already submitted this response. Are you sure this is right?</p>
}
</div>
Link naar pp
</div>
Capture the return from AddResponses in a boolean variable and set a custom property in the ViewBag object
bool result = repository.AddResponse(guestResponse);
ViewBag.Response = result;
return View("Thanks", guestResponse);
Now in the Thanks view you can use this property to decide which text to write
#model PartyInvites.Models.GuestResponse
#{
ViewBag.Title = "Thanks";
bool response = (ViewBag.Response != null ? Convert.ToBoolean(ViewBag.Response) : false);
}
.....
#if (!response) {
#:<p>You already submitted this response. Are you sure this is right?</p>
}
I am trying to learn how to use TryUpdateModel but I cannot get it to work, you can find my code below:
Controller Side
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace EFW6.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
private WorkFlowContext context = new WorkFlowContext();
public ActionResult Index()
{
return View();
}
[HttpPost]
public string UploadFile(FormCollection form)
{
Files file = new Files();
if (TryUpdateModel(file, form.ToValueProvider()))
{
return "True " + file.filePath;
}
else
{
return "False";
}
}
}
}
View Side
#{
ViewBag.Title = "index";
}
<h2>#Model</h2>
<form method="post" action="Home/UploadFile">
<input type="text" name="filePath">
<input type="submit">
</form>
Model Class
class Files
{
public string filePath;
}
When I return the value of the file path it returns nothing while it returns the value True for as a result for the operation.
the problem is that you I am using field instead of property in the Files Class
You have to change it to be like this
class Files
{
public string FilePath { get; set; }
}