MVC3 ASPX view object does not contain definition - asp.net-mvc

I started this project using MVC2, but changed to the MVC3 dll.
I have an Asset entity. In the controller I have the Details ActionResult defined like this:
EDIT: (Put the correct controller code.)
public ActionResult Details(int id)
{
using (var db = new AssetsContainer())
{
return View(db.Assets.Find(id));
}
}
My Details.aspx page is defined this way:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<CITracker.Models.Asset>" %>
<%# Import Namespace="CITracker.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Details
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Details</h2>
<fieldset>
<legend>Fields</legend>
<div class="display-label">Id</div>
<div class="display-field"><%: Model.Id %></div>
I get this error:
CS1061: 'object' does not contain a definition for 'Id' and no extension method 'Id' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
Any ideas why this was working with MVC2 but fails with MVC3? I don't get develop time errors, but I do get runtime errors.

I am not sure, but looks like this is the problem. You are passing a List to the view
return View(db.Assets.ToList());
but your Inherits says
Inherits="System.Web.Mvc.ViewPage<CITracker.Models.Asset>" instead of
Inherits="System.Web.Mvc.ViewPage<IEnumerable<CITracker.Models.Asset>>"
And also since your model is now a IEnumerable, you can not do a simple Model.Id instead it should be Model[0].Id (or what ever ith elemnt you choose or you do a foreach)

This is an old question, but I ran into the same problem converting some MVC 2 code to MVC 3. A simple configuration problem to look for is making sure you have this app setting in your config:
<appSettings>
<add key="enableSimpleMembership" value="false" />
</appSettings>
See this thread for more info.

Related

ASP.NET MVC - Html.RenderPartial issues

I have a usercontrol named "LoginUserControl.ascx" which I have placed in a master page.
Header of "LoginUserControl.ascx"
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MultiTechnologyWeb.Models.loginmodel>" %>
Then I used the below code to show the usercontrol in the masterpage.
<% Html.RenderPartial("LoginUserControl"); %>
On first run the page "index" is loaded.
Notice the header of the "index" page, no model is specified. Thus page load successfully
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MT.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
Now I click on the link to open register.aspx. I got the below error
The model item passed into the dictionary is of type 'MultiTechnologyWeb.Models.registermodel', but this dictionary requires a model item of type 'MultiTechnologyWeb.Models.loginmodel'.
Header of "register.aspx" page
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MT.Master" Inherits="System.Web.Mvc.ViewPage<MultiTechnologyWeb.Models.registermodel>" %>
So to my understanding model is being interchanged, so anybody can please help me on how to resolve this issue
More Explanation.............LATEST
I have debug, i know that the crash is occuring after the actionresult for register is finished execution.
Code below is for actionresult "register"
public ActionResult register()
{
registermodel model;
//some code here
return View("register",model);
}
So i'm just returning one type of model that is "registermodel", Would it be possible to return another model such as "loginmodel" by using a list or array to return multiple models in the same view.
You should use <% Html.RenderAction("Logon","Account"); %> in your MasterPage instead of using RenderPartial and in this action you just return the login partial you want to use in the header
public ActionResult Logon(){
// do your stuff
return PartialView("LoginUserControl");
}
By this way you could pass the loginmodel to the LogInPartial and pass registermodel to the register page
Please not that RenderAction and RenderPartial are not the same.
RenderPartial will render only the view. While RenderAction will make a new MVC roundtrip, by making a new instance of the controller etc and returning the result.
To solve your issue you could pass in the MultiTechnologyWeb.Models.loginmodel where you call <% Html.RenderPartial("LoginUserControl"); %>. It would look like this:
<% Html.RenderPartial("LoginUserControl", new MultiTechnologyWeb.Models.loginmodel()); %>
Or:
<% Html.RenderPartial("LoginUserControl", Model.LoginModel); %>
If you're not wanting to send a model to your partial view, which I've wanted to do in the past, you do have to at least pass something to the RenderPartial method.
This was the only method I could find that allowed me to now have to pass a model. I tried passing null and it continued to pass the parent model
<% Html.RenderPartial("LoginUserControl", new ViewDataDictionary()); %>

Reusable components in ASP.NET MVC

I have feature on my website (some UI and associated functionality) that I want to be able to reuse on multiple pages. For the purposes of this question, let's say it's a "Comments" feature.
There is an area in my application for Components and within the area are a controller: /Controllers/CommentController, and two partial views: /Views/Comment/Index.ascx (for listing comments) and /Views/Comment/Create.ascx (for creating comments).
CommentController looks something like this:
public class CommentController : Controller
{
[ChildActionOnly]
public ActionResult Index()
{
return PartialView(GetComments());
}
[HttpGet]
[ChildActionOnly]
public ActionResult Create()
{
return PartialView(); //this is wrong.
}
[HttpPost]
[ChildActionOnly]
public ActionResult Create(FormCollection formValues)
{
SaveComment(formValues);
return RedirectToAction("Index"); //this is wrong too.
}
}
Index Partial View:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<div>
<% foreach (var item in Model) { %>
<div>
<%: item.Comment %>
</div>
<% } %>
<%: Html.ActionLink("Add a Comment", "Create", "Comment", new { area = "Components" }, null) %>
</div>
Create Partial View:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<div>
<% using (Html.BeginForm())
{%>
Enter your comment:
<div>
<input type="text" name="comment" />
</div>
<p>
<input type="submit" value="Create" />
<% //also render a cancel button and redirect to "Index" view %>
</p>
<% } %>
</div>
The Index partial view is included in a view with RenderAction, like so:
<% Html.RenderAction("Index", "Comment", new { area = "Components" }); %>
This code doesn't work because the forms within the partial views submit to actions on the CommentsController that are marked [ChildActionOnly] (this is by design, I don't want the "Components" to be requested independently of a hosting page).
How can I make this "component" approach work, i.e. have a partial view that submits a form to change the state of a component within a page without losing the hosting page itself?
EDIT:
To clarify, the use of [ChildActionOnly] is not my problem here. If I remove the attribute from my action methods, my code only "works" in that it doesn't throw an exception. My "component" still breaks out of its hosting page when its form is submitted (because I'm telling the form to submit to the partial view's URL!).
You are making MVC fight itself by asking a form to target an action that is marked as ChildActionOnly.
My solution to this problem when I was designing a highly reusable wizard framework, was to NOT mark the actions as ChildActionOnly but instead to detect if the request was an ajax one or just a plain vanilla request.
The code for all this is packaged into a base controller class. In your derived controllers, you do something like:
[WizardStep(4, "Illness Details")]
public ActionResult IllnessDetails()
{
return Navigate();
}
Where the Navigate() method of the base controller has decided whether to return the full view or just the partial view, depending on whether it is, or isn't, an ajax request. That way, you can never return the partial view in isolation.
To ascertain if it is an Ajax request, I used a combination of Request.IsAjaxRequest() and TempData. The TempData is needed because my wizard framework implements the PRG pattern out of the box, so I need to persist the fact that the original post was an ajax one.
I guess this is just one solution and it took a bit of trial and error to get it right. But now I live happily ever after developing wizards like I was JK Rowling...
Use Ajax to post the partial.

Why can't I share a variable between two content sections in an ASP.NET MVC View?

I have an ASP.NET MVC View with the typical TitleContent and MainContent, with a fairly complicated title that I want to calculate once and then share between these two content sections, like so:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%
var complicatedTitle = string.Format("{0} - {1}", Model.FirstThing, Model.SecondThing);
%>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%: complicatedTitle %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2><%: complicatedTitle %></h2>
</asp:Content>
This, however, doesn't work, as the resulting error message would say that only Content controls are allowed directly in a content page that contains Content controls.
The calculation definately belongs in the view. How do you solve this problem?
The reason the code cannot be outside a Content control is because it needs to be in a server-side section of some type for the server to be able to automatically render it.
I'd suggest that it would be more common for this title to be constructed in your Controller Action method and saved to ViewData.
Another way is by adding an HTML helper specifically to produce the well-formatted title.
public static string FormattedTitle(this HtmlHelper helper, string firstPart, string secondPart)
{
return firstPart + secondPart;
}
and then invoke it with
<%: Html.FormattedTitle(firstPart, secondPart) %>
here's one way : [Edit: looks like this one results in a static field - so don't use this - sorry]
<Script runat="server" language="C#">
string foo = "first thing " + " second thing";
</Script>
<asp:Content ContentPlaceHolderID="head" runat="server">
<%= foo %>
</asp:Content>
<asp:Content ContentPlaceHolderID="body" runat="server">
<%= foo %>
</asp:Content>
(note you can't use 'var' in Script)
and a second way :
Use code-behind to calculate the property with a ComplicatedTitle property that private to the view. You're still completely relying on the view to perform the logic, but taking it out of the HTML part of the view - after all your aspx and aspx.cs file end up becoming the same class in the end anyway!
Some people are freaked out by code in views, but I think it definitely has its place if you're cautious and sensible
and a third way :
i'm assuming you don't want to make a third property in your model but heres a quick and dirty way if it ever seems appropriate. at least your controller is not doing it, but this probably isn't the best way
public class MyModel {
public string Prop1 {get;set;}
public string Prop2 {get;set;}
public string GetFormattedTitle() {
return Prop1 + " - " + Prop2;
}
}

can you post complex objects from form to controller in asp.net mvc

i see there are solutions using different model binders like castl but i didn't know if the basic default model binder supported nested complex objects when i am posting a form to a controller.
I think you can if I understand your question.
In the name of my field I not only put the property name but object as well.
So if I have a "Person" object that contains an "Address" object that contains a "State" field I would have as the name "Person.Address.State" and that seems to resolve just fine in my controller.
<%= Html.TextBox("Person.Address.State", Person.Address.State....
Is this what you are asking?
EDIT
It does work and here is the code to get it to work.
namespace DoMyWork.Controllers
{
public class test
{
public string value { get; set; }
}
public class testParent
{
public test test { get; set; }
}
public class SearchController : Controller
{
public ActionResult ViewUserControl1(testParent test)
{
UpdateModel(test);
return View(test);
}
SNIP
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<DoMyWork.Controllers.testParent>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
ViewUserControl1
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>ViewUserControl1</h2>
<% using( Html.BeginForm()){ %>
<%= Html.TextBox("test.value", Model.test.value) %>
<input type="submit" value="sdf" />
<%} %>
</asp:Content>
I had the same problem and I found a similar question that helped a lot of people to solved this: Complex object and model binder ASP.NET MVC, but it didn't solve my problem.
I realized that the problem was caused because my inputs were disabled (I was disabling them with JQuery on document ready) as you can see it here: How do I submit disabled input in ASP.NET MVC?. At the end I used read-only instead of disabled attribute.

MVC invoking default page when opening a different page?

I've got a simple MVC (RC1) app set up, and I'm seeing some odd behavior. The Home/Index page shows a list of items using a ListView. Here's the HomeController code:
Function Index()
ViewData("results") = From m In context.MyTable
Return View()
End Function
The Home/Index.aspx page just has a ListView on it, and the code behind has this:
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
MyListView.DataSource = ViewData("results")
MyListView.DataBind()
End Sub
This works fine when navigating to Home/Index. However, I've got another view and controller called Form. It's just a stub right now, so here's the FormController:
Function Index()
Return View()
End Function
The Form/Index.aspx has no code behind - again, just a stub.
The problem I'm seeing is that when I try to navigate to Form/Index, I get "Object reference not set to an instance of an object." on the code behind of Home/Index.aspx.vb. Why is this? I'm trying to navigate away from that page - why is it trying to execute the code behind? If I wrap the code like this:
If ViewData("results") IsNot Nothing Then
MyListView.DataSource = ViewData("results")
MyListView.DataBind()
End If
everything functions correctly, but it doesn't seem like I should have to do that. Am I missing something?
Update: Per request, here's the contents of Form/Index.aspx:
<%# Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="ProviderFeedback.Index" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h3>
Enter Provider Feedback
</h3>
<form method="post" action="/Form/CreateNew">
<%=Html.TextBox("member")%>
<input type="submit" value="Submit" />
</form>
</asp:Content>
Is this right?
Inherits="ProviderFeedback.Index"
Shouldn't that be Form.Index?

Resources