public definition of GetEnumerator in asp.net mvc missing? - asp.net-mvc-2

Should I manually create a definition for GetEnumerator? Seems like it should know...
I get the following error:
foreach statement cannot operate on
variables of type
'MvcAppNorthwind.Models.Product'
because
'MvcAppNorthwind.Models.Product' does
not contain a public definition for
'GetEnumerator'
Line 9: <h2><%: ViewData["Message"] %></h2>
Line 10: <ul>
Line 11: <% foreach (MvcAppNorthwind.Models.Product p in ViewData.Model) { %>
Line 12: <li><%= p.ProductName %></li>
Line 13: <% } %>
In my controller I have this code:
NorthwindDataContext db = new NorthwindDataContext();
ViewData["Message"] = "Welcome to ASP.NET MVC!";
var products = from p in db.Products
select p;
return View(products);
I changed the declaration in my view like this and now it works:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcAppNorthwind.Models.Product>>" %>
But if you want to display or use data from several models in the same view? How do you do it then?

Change the type of "products" from var to IEnumerable<MvcAppNorthwind.Models.Product> and make sure your cast reflects the same.
In answer to your last question, you could assign objects to a dictionary item in ViewData OR better yet you could create a View Model that contains all of the data that you need for the view. That way you have better separation of concerns by having a model that is specific for your view.

Related

Is there a method to write a response in an EJS template?

With classic ASP you can do a response.write('foo') inside <% ... %>. Is this possible with EJS?
The current workaround is to use 2 tags, one for logic, one for output:
<%
let someString = generateSomeStringHere()
%>
<%- someString %>
I do understand that some will recommend generating someString outside of the template but let's say for the sake of argument that is not desirable.
We would like to do:
<%
let someString = generateSomeStringHere()
ejs.write(someString);
%>

mvc2 dropdownlist dynamic parameters

<% string disabled="new {disabled='disabled'}"; %>
<%= Html.DropDownList("clientId", someObject, disabled)%>
In the above code I want the text disabled to be replaced by what ever value I set that string to. When I check the HTML source on the page, I see that new {disabled='disabled'} has been added as a new item in the dropdown list instead of a property. How do I fix this?
The third parameter of DropDownList helper must be an object that contains the HTML attributes or object of type IDictionary<string, object>.
This is the proper solution:
<% var disabled = new { disabled = "disabled" }; %>

ASP.NET MVC 2: foreach, RenderPartial, ViewModel

I'm trying to employ a technique that I came across that seems quite clean.
Previously, my Partial had the loop inside of it. I was looping through the mode within the Partial... but then I came across an example where the foreach loop existed in the main page, while the partial was just the meat of the loop.
They accomplished it like so:
<% int index = 1; // iteration
foreach (var item in Model.Deal) { %>
<% Html.RenderPartial("DealList", item, new ViewDataDictionary {{ "index", index }}); %>
<% i++; // increase the interation
} %>
But in my example, I'm using a ViewModel, and now that I'm in the partial, I can't access "item" like I used to be able to. Instead my only option is Model.Deal ...
What is the point of passsing "item" with the RenderParial helper if I can't access it by saying item.StoreName? Note, both the View and the Partial are strongly typed to the same ViewDataModel.
Inside of the partial "DealList" your model will be whatever item is in the main view. Inside of the partial view, Model.Deal refers to a Deal object inside of item (from the main view).
This means that your StoreName property will be accessible as Model.StoreName within your partial view.
As a side note, I put together an extension method to deal with rendering of multiple partial views so as to not require the looping.
The new method is called RenderPartials:
public static void RenderPartials(this HtmlHelper helper, string partialViewName, IEnumerable models, string htmlFormat)
{
foreach (var view in models.Select(model => helper.Partial(partialViewName,model)))
{
helper.ViewContext.HttpContext.Response.Output.Write(htmlFormat, view.ToHtmlString());
}
}
Using this method you can simple say:
<% Html.RenderPartials("DealList",Model.Deal); %>
inside your main view, without the loop.
There's some more information about this here which explains more about the htmlFormat parameter etc.
Hope this is helpful to you.
#model IEnumerable<dynamic>
#foreach (dynamic m in Model)
{
#Html.Partial(MVC.Lists.Messages.Views._SingleMessage, (object)m)
}

Outputting data whilst in a partial view

I have some MVC2 code that loops a collection of type Product held within the view model. Each time I want to output the data I have to use <%: %> along with using <% %>, for example:
<% foreach (Product item in Model.ProductsCollection) {
if (item.doesExist == true) { %>
<%: item.name %>
<% } %>
Is there any way to still output item.name without having to close & open tags, e.g. in classic asp we used response.write()?
I appreciate the need to encode data using <%: %>, and am not wanting to bypass this, just wanting to output the encoded data without needing the bracket overhead.
Thanks
You can use Response.Write() in conjunction with Html.Encode()
<% foreach (Product item in Model.ProductsCollection) {
if (item.doesExist == true) {
Response.Write(Html.Encode(item.name));
}
} %>
Not in aspx view engine, sir.
Check out MVC3 rc2 and #razor view engine.
#razor is the Man.

Display empty textbox using Html.TextBoxFor on a not-null property in an EF entity

I am using Entity Framework (v4) entities. I have an entity called Car with a Year property of type integer. The Year property does not allow NULL. I have the following in my Create view:
<%= Html.TextBoxFor(model => model.Year) %>
I am required to return a new Car object (due to other requirements) in my HttpGet Create action in the CarController.
Currently, a zero is displayed in the Year textbox because the Year property does not allow NULL. I would like to display an empty textbox in the Create view. How do I do this?
Use Html Attributes Overload. In razor it would be:
#Html.TextBoxFor(model => model.Year, new { Value = "" })
Try this instead:
Html.TextBox("Year", "")
If you are using the strongly typed TextAreaFor helper, then there is no direct way to set a default value. The point of the strongly typed helper is that it binds the text area to a model property and gets the value from there. If you want a default value, then putting in the model would achieve that. You can also just switch to the non-strongly typed TextArea helper. It gives you more a bit more flexibility for cases like this:
#{
var defaultValue= "";
}
#Html.TextArea("Model.Description", defaultValue, new { Value = "added text", #class = "form-control", #placeholder = "Write a description", #rows = 5 })
Try this is you are trying to append to your field or want to modify an existing field with an empty TextBoxFor.
Html.TextBoxFor(model => model.Year, Model.Year="")