Spark View Engine and using viewdata confusion - asp.net-mvc

I can't seem to get a grasp on how to use the viewdata structure in the spark view engine. I have the following code in my controller:
// Retrieve the project list from the database
var projects = from p in _context.Repository<project>()
orderby p.name ascending
select p;
return View(projects.ToList<project>());
This code works, as I have unit tests returning the correct projects, and my non-spark view worked perfectly. Now I am trying to switch to Spark View Engine and I'm just confused on the syntax. As a side note, I have verified that spark view engine is working and reading my .spark view.
Here is what I am using in my list.spark view:
<h2>Available Projects</h2>
<viewdata model="IList[[project]]"/>
Count: ${model.count}
When rendering this view the following error occurs:
.../List.Spark(3,16): error CS0103: The name 'model' does not exist in the current context
This is referring to the model.count line. Why doesn't this work? I tried passing the project list to the ViewData["projects"] (and replaced model in the spark code with projects) and I get the same error (take out the model.count for projects.count).
This is probably something stupid, but I can't seem to figure this out.
Update:
Well I fixed this. It seems that the MVC2 web.config file created by VS 2010 Beta 2 was bad. I used a MVC2 web.config file created by VS 2010 RC and it now works. Thanks!

I think you want this:
<h2>Available Projects</h2>
<viewdata model="IList[[project]]"/>
Count: ${ViewData.Model.Count}
or this:
<h2>Available Projects</h2>
<viewdata model="IList[[project]]"/>
<var model="ViewData.Model" />
Count: ${model.Count}
The viewdata element declares the types of the entries in the ViewDataDictionary. For "model", this is actually declaring the type of the ViewDataDictionary's Model property.
Note also that these expressions and type names are C# code, and thus case sensitive.
EDIT: syntax updated for 1.0 stable release.
Reference - using view data in the documentation

Related

Umbraco 7 when to use #Umbraco vs #CurrentPage vs #Model in Razor views?

As the title says, when should I use #Umbraco, #CurrentPage or #Model in Razor views to get properties from a node.
#Model.Content.GetPropertyValue() returns a strongly typed object, whereas #CurrentPage returns a dynamic object. However, with #Umbraco I can get a dynamic (#Umbraco.Content()) or a strongly typed object (#Umbraco.TypedContent()).
Can #Umbraco helper do everything that #CurrentPage and #Model can do? When should I be using which, and why?
You answered most of your question yourself. #Model and #CurrentPage are the same except #CurrentPage is dynamic. Both return the current page. That means that, if you interit your views from UmbracoViewPage, you can not use #CurrentPage because this is only available on the UmbracoViewTemplate. Personally I like #Model more than #CurrentPage, but it's a personal choice
#Umbraco is a completely different beast. It does not return the current page, but it has a bunch of methods to get other content, media and members in different ways (e.g. xpath). But also templating and misc methods like:
Umbraco.If(condition, trueValue [, falseValue])
Umbraco.Trunctate // limit text size
Umbraco.StripHtml // remove html tags
Umbraco.Search // full text search
To know more about the #Umbraco, visit the Umbraco helper documentation
E.g. If you got an image ID from the current node using
var imgId = #Model.Content.GetPropertyValue<string>("img")
then you could use #Umbraco.TypedMedia(imgId) to get the image IPublishedContent object.
Update:
Next to #Umbraco.Field("propertyAlias") which is one of the template helpers, you can also use #Umbraco.Field( x, "propertyAlias") where x is an IPublishedContent. This will always return an IHtmlString which makes it impractical for other programming efforts, but makes the Umbraco.Field() a very nice helper method to return properties.
Update 2:
Starting from version 7.4, There is a modelBuilder which allows you to define UmbracoTemplatePage<ContentModels.HomePage> and use #Model.Content.BodyText later on. Starting from Umbraco v8 (on the roadmap), support for dynamics (CurrentPage on UmbracoTemplatePage) is said to be dropped. So prepare by using ModelsBuilder and UmbracoViewPage<MyModel>.
Update 3:
Starting from version 8, there will be only an UmbracoViewPage. That means that CurrentPage will not be available anymore. Try to use the "models builder" approach to be future proof or read the first v8 documentation about this topic.

Umbraco Razor - binding content fields

I've created a template (View) in Umbraco (MVC) and am trying to figure out how to bind to the document type content. Keeping it really simple:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = null;
}
<h1>#Model.Title</h1>
My Umbraco document type has a Title field (alias is 'title') but if I try and run this I get build errors. I've found a whole load of documentation suggesting using a Library.NodeById() method but I believe that's for WebForms and not MVC. Can anyone offer some guidance?
You can get a property value in multiple ways with Model::
#Model.Content.GetPropertyValue("title")
#Model.Content.GetProperty("title").Value
And as a dynamic
#CurrentPage.Title
Did you remember to add your template to your document type?
You can also use the Field helper method:
#Umbraco.Field("myFieldName")
nice thing about this helper is that you can also specify alternative fields (if the first one was empty.
You can find this back in the documentation:
http://our.umbraco.org/documentation/reference/templating/Mvc/views#RenderingafieldwithUmbracoHelper

EditorTemplates/Object.cshtml using EditorFor() instead of Editor()?

I am trying to create a generic editor template that replicates Html.EditorForModel(), to later customize and build upon. Brad Wilson's template gets pretty close, but I found that it chokes when the same key exist in both ViewData (or ViewBag) and the model. For example ViewBag.Title causes problems if the view model also has a Title property.
I learned here that using strongly-type helpers (i.e. Html.EditorFor(x => x.Title) instead of Html.Editor("Title") seems to help. So I tried to modify Brad's template, but I ran into a brick wall, as nothing I tried so far has worked. I can't figure out how to use strongly-typed helpers in a context where I don't know the model type, like an editor template for example.
Is there any way to create an Object template like Brad's, but using strongly-typed helpers (i.e. LabelFor, EditorFor, ValidatorMessageFor) instead of weakly-typed ones (i.e. Label, Editor, ValidatorMessage)?
Thanks.
I solved this problem in a slightly roundabout way, by removing the ViewData right before the call to #Html.Editor and then putting it back after.
Object.cshtml:
object oldViewData = null;
var hasConflictingViewData = ViewData.TryGetValue(prop.PropertyName, out oldViewData);
if (hasConflictingViewData)
{
ViewData.Remove(prop.PropertyName);
}
#Html.Editor(prop.PropertyName)
if (hasConflictingViewData)
{
ViewData.Add(prop.PropertyName, oldViewData);
}
The only other option I could think of is using a ton of reflection to call EditorFor generically with a runtime type, and pass in an expression for the pertinent property.
You can view all of the code for the new Object.shtml by going and downloading the MVC source code. I thought it was also in some common folder on your pc already but I can't remember where.
http://aspnet.codeplex.com/releases/view/58781

Include in enity framework 4

I've been using enity framework that came with 3.5sp. And now I've redone things for enityframework 4 and asp.net mvc 2. I've come across something (which worked in my previous version and asp.net mvc 1.0).
I have this:
public IQueryable<Booking> GetBookings()
{
return from b in _entities.Bookings.Include("BookingObject")
select b;
}
And in my controller I have:
return View("Index", new BookingsViewModel
{
Bookings = _br.GetBookings().ByDay(DateTime.Today)
});
And it doesnt seem to include the "BookingObject"-entity, so I can type like <%= Model.Bookings.BookingObject.BookingObjectName %> in my view.
What might be missing here? Do I need to turn something on in the diagram for it to include entities or?
/M
No, it should work exactly as before. I'm assuming you have a navigation property BookingObject on your Booking item - but then the .Include() would error out if you didn't. I don't think there's anything else you need to set up, or at least not that isn't done by default. I'd verify the definition of the navigation property in the .edmx editor at least.
You're definitely using the final RTM EF4 code? We hit a bug in the final RC building incorrect SQL and returning no results for one specific include sequence, but it was a lot more complex than that.
Failing that I would use SQL Server Profiler to trace out the SQL it's using and try and debug that.

MVC Contrib Input Builders and Spark View Engine

In Eric Hexter's Input Builders, different templates use different strongly-typed models; for example String uses PropertyViewModel<object>, DateTime uses PropertyViewModel<DateTime>, Form uses PropertyViewModel[], and so forth. Spark View Engine doesn't seem to allow this, because all elements that compose the presentation (masters, views, partials, etc.) are compiled into a single class.
If I try to setup a view involving more than one template, I get the following exception:
Only one viewdata model can be declared. PropertyViewModel<DateTime> != PropertyViewModel<object>
If leave just one viewdata declaration, I get another exception about the passed model item mismatching the required one.
It seems like I will have to give up either the Input Builders or Spark, which is sad because I really love both. So I thought I'd ask here to see if anybody has already figured this out.
Thanks.
You can always use <% Html.RenderPartial() %> for partial view rendering with different model. This will create more than one view class.

Resources