Get Image ID of Child Item - umbraco

I'm trying to get the ID of a child item's image property so I can use Umbraco.Media() to display the image.
I'm trying to use best practice by using strongly-typed models and I think I've called the strongly-typed models correctly here.
Why is the following code returning the 'Object reference not set to an instance of an object' error at the 'var imageId = location.LocationImage.Id;' line?
Thank you.
#inherits Umbraco.Web.Mvc.UmbracoViewPage<ContentModels.Locations>
#using ContentModels = Umbraco.Web.PublishedModels;
#{
Layout = "master.cshtml";
var locations = Model.Children<Location>();
}
#foreach (var location in locations)
{
<p>#location.LocationName</p> //this returns a string as expected
var imageId = location.LocationImage.Id; //this throws the error
var image = Umbraco.Media(imageId);
<img src="#image"/>
}
For info, I've enabled AppData ModelsMode and rebuilt the models. The implementation in my Location.generated.cs is:
/// Location Image
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.0.4")]
[ImplementPropertyType("locationImage")]
public Image LocationImage => this.Value("locationImage");

This was solved on the Umbraco forums so I'll post the answer here.
With Umbraco strongly-typed models you can pass the value inline to the html tag, e.g.:
<img src="#location.LocationImage.Url"/>
Instead of having to pass it to a service.

Related

Getting error when multiple results passing to view in asp.net MVC5

I use asp.net mvc 5 and EF 6 .I have following code in my controller
var resultOne = stats.GetPlayerStatsByParam(year, modeOne); //first
ViewData["more"] = stats.GetTeamStatsID(year); //second
return View("StatsNew", resultOne.ToList());
I am able to display result in view using "resultOne". Now I want to pass another data to same view using ViewData[]. its a stored procedure and the result is paasing to "ViewData["more"]".
I have done following code for "ViewData["more"]" in View page
But I am getting an error saying that 'object reference not set'
#foreach (var item in ViewData["more"] as #List<demo.GetTeamStatsID_Result>)
{
#item.Pld;
}
Use a viewmodel and extend it by the data coming from stats.GetTeamStatsID(year);
Do not use ViewBag or ViewData if not necessary for some reason (which I canĀ“t imagine right now)
As the comments have already pointed out, build a ViewModel class, that wraps everthing you need:
//I am using fake types here, sinceI don't know your model classes
//substitute accordingly!
public class MyViewModel
{
public PlayerStatsType PlayerStats { get; set;}
public List<demo.GetTeamStatsID_Result> Teams { get; set;}
}
Then in your action method:
var vm = new MyViewModel();
vm.PlayerStats = stats.GetPlayerStatsByParam(year, modeOne); //first
vm.TeamId = stats.GetTeamStatsID(year); //second
return View("StatsNew", vm);
Amend the model declaration in your view:
#model Namespace.Models.MyViewModel //again use namespace for your vm class
Now you can access both properties from your model:
#foreach (var item in Model.Teams)
{
#item.Pld;
}

MVC Sitecore View pass attribute to property

So my problem is like this. In sitecore view i can write someting like this:
#Html.Sitecore().Field(PictureID.ToString(), Model.Person.Item, cssClass: "img-responsive");
which will get me the HtmlString for the field with ID PictureID on the item Model.Person.Item and in that HtmlString i will have a cssClass added. So the result will be something like
<img src="xxxx" class="img-responsive"/>
For this View the Model will be RenderingModel. But what if i have a Person as a model and this person would have a property called Picture which will be retrieved somewhere in the code behind so that in the view i would have
#Model.Picture
How do i connect the view, controller and model so that from the view i send somehow the cssClass that i want that Picture to have when the HtmlString is returned.
You need to pass the class name to the renderField pipeline.
So if Model.Picture is a HtmlString containing the output of the renderField pipeline the class name cannot be decided dynamically in the View but need to be set in the Model (it can be discussed if this is a nice approach).
Anyway when you create your model you can pass the class name into the renderField pipeline as follows:
var renderFieldArgs = new RenderFieldArgs
{
Item = this.Item,
FieldName = "PICTURE FIELD ID"
};
TypeHelper.CopyProperties(parameters, new {#class = "img-responsive"} );
CorePipeline.Run("renderField", renderFieldArgs);
return new HtmlString(renderFieldArgs.Result.FirstPart);
This will mean that Model.Picture always will have the same class name.
Otherwise you could have a method on your Model class accepting a class name string as parameter. Something like
public HtmlString GetPictureMarkup(string className)
{
var renderFieldArgs = new RenderFieldArgs
{
Item = this.Item,
FieldName = "PICTURE FIELD ID"
};
TypeHelper.CopyProperties(parameters, new {#class = className} );
CorePipeline.Run("renderField", renderFieldArgs);
return new HtmlString(renderFieldArgs.Result.FirstPart);
}
Hope it helps.

Weird razor behavior with List<dynamic>

This is my controller's code:
IQueryable<Foo> foos = dbContext.Foos.Where(...);
return View(foos);
And this razor code (cshtml) works well:
#model IQueryable<Foo>
#{
IQueryable<Foo> foos = Model;
var projected = foos.Select(e => new
{
fooId = e.FooId,
bar = new
{
barId = e.Foo.BarId
}
}).ToList();
}
#foreach (var x in projected)
{
<span>#x.fooId</span><br />
}
But this razor code (cshtml) doesn't work, being almost the same thing!:
#model IQueryable<Foo>
#{
IQueryable<Foo> foos = Model;
var projected = foos.Selected(Foo.Projection()).ToList()
}
#foreach (var x in projected)
{
<span>#x.fooId</span><br />
}
Foo.Projection() is a static method that I reuse a lot:
public static Expression<Func<Foo, dynamic>> Projection()
{
return e => new
{
fooId = e.FooId,
bar = new
{
barId = e.Foo.BarId
}
}
}
I'm getting that famous error: 'object' does not contain definition for 'fooId', which is discussed in here: MVC Razor dynamic model, 'object' does not contain definition for 'PropertyName' -but none of those answers helped me.
The accepted answer says: "now that MVC 3 has direct support for dynamic, the technique below is no longer necessary", so I also tried to return the projected List<dynamic> to the view ("ready to use, no projection needed") and it didn't work either (getting the same error). This is the code for that attempt:
Controller's code:
List<dynamic> foos = dbContext.Foos.Select(Foo.Projection()).ToList();
return View(foos);
View's code:
#model dynamic
etc.
Edit: With the debugger I'm able to check (just after the exception is thrown) that the item indeed has "a definition for..." (in the example code the item is x, but here is lot)
When you use dynamic you instruct the compiler to use reflection to call methods and access properties. In your case the objects that you access in this way are anonymous types and anonymous types are internal to the assembly they are created in.
The code generated for the Razor view is in a separate assembly and trying to reflect over an anonymous type created in the controller will fail. The debugger is not affected by this limitation so when the reflection fails and throws an exception you are still able to inspect the properties of the anonymous type in the debugger.
This also explains why your code works when you create the anonymous type in the Razor view. Then the code generated by your use of dynamic is able to reflect over the anonmyous type because it is declared in the same assembly.
Essentially, in MVC Razor you are not able to use anonymous types in a view when they are declared in the controller. Your use of dynamic was hiding this underlying problem by generating a run-time error that was hard to understand.
To fix your problem you can either create specific public types instead of using internal anonymous types or you can convert the anonymous type to an ExpandoObject in the controller.
I suppose that View() contructor just don't know what overload to use, since you have dynamic type. You can try to do this:
List<dynamic> foos = dbContext.Foos.Select(Foo.Projection()).ToList();
ViewData.Model = foos;
return View();
But why do you want to use strongly typed View if you don't use any of strongly typed ViewModel advantages, like type check and IntelliSense?
If you really want to pass dynamic type to your View since MVC 3 you can use ViewBag that already is dynamic.
In your Controller:
List<dynamic> foos = dbContext.Foos.Select(Foo.Projection()).ToList();
ViewBag = foos;
return View();
In your View:
#foreach (var x in ViewBag)
{
<span>#x.fooId</span><br />
}
inside the controller
List foos = dbContext.Foos.Select(Foo.Projection()).ToList();
return View(foos);
in side razor view
#model List<dynamic>

passing value in partial view viewdatadictionary

#Html.Partial("~/Areas/WO/Views/PartialContent/_FirstPage.cshtml", new ViewDataDictionary { { "WOID", WOID } })
In my Page i am accessing Partial view in the above way.
I need to pass WOID(view data dictionary) value from query string, For that i am using following Code
#{
var desc = Html.ViewContext.HttpContext.Request.QueryString.Get("ID");
Uri referrer = HttpContext.Current.Request.UrlReferrer;
string[] query = referrer.Query.Split('=');
int WOID = Convert.ToInt32(query[1]);
}
But the issue is this code is working in all browsers except I.E. i Need to Solve this problem.
Please help me
Instead of this you can have this value as part of you model and use that.That is the standard and recommeded way .
In your action method you can have these as parameter.Your query string value will get bind to this parameter
public ActionResult ActionMethod(int ID)
{
Model.WOID = WOID;
// Other logic
return View(Model)
}
Next step you can add this as a property to your view model or add it to ViewData dictionary and then access it in your partial view.

How to display a list using ViewBag

Hi i need to show a list of data using viewbag.but i am not able to do it.
Please Help me..
I tried this thing:
ICollection<Learner> list = new HobbyHomeService().FetchLearner();
ICollection<Person> personlist = new HobbyHomeService().FetchPerson(list);
ViewBag.data = personlist;
and inside view:
<td>#ViewBag.data.First().FirstName</td>
But this does not show up the value and gives error saying "Model.Person doesnot contain a defibition for First()"
In your view, you have to cast it back to the original type. Without the cast, it's just an object.
<td>#((ViewBag.data as ICollection<Person>).First().FirstName)</td>
ViewBag is a C# 4 dynamic type. Entities returned from it are also dynamic unless cast. However, extension methods like .First() and all the other Linq ones do not work with dynamics.
Edit - to address the comment:
If you want to display the whole list, it's as simple as this:
<ul>
#foreach (var person in ViewBag.data)
{
<li>#person.FirstName</li>
}
</ul>
Extension methods like .First() won't work, but this will.
To put it all together, this is what it should look like:
In the controller:
List<Fund> fundList = db.Funds.ToList();
ViewBag.Funds = fundList;
Then in the view:
#foreach (var item in ViewBag.Funds)
{
<span> #item.FundName </span>
}
simply using Viewbag data as IEnumerable<> list
#{
var getlist= ViewBag.Listdata as IEnumerable<myproject.models.listmodel>;
foreach (var item in getlist){ //using foreach
<span>item .name</span>
}
}
//---------or just write name inside the getlist
<span>getlist[0].name</span>
i had the same problem and i search and search .. but got no result.
so i put my brain in over drive. and i came up with the below solution.
try this in the View Page
at the head of the page add this code
#{
var Lst = ViewBag.data as IEnumerable<MyProject.Models.Person>;
}
to display the particular attribute use the below code
#Lst.FirstOrDefault().FirstName
in your case use below code.
<td>#Lst.FirstOrDefault().FirstName </td>
Hope this helps...
Use as variable to cast the Viewbag data to your desired class in view.
#{
IEnumerable<WebApplication1.Models.Person> personlist = ViewBag.data as
IEnumerable<WebApplication1.Models.Person>;
// You may need to write WebApplication.Models.Person where WebApplication.Models is
the namespace name where the Person class is defined. It is required so that view
can know about the class Person.
}
In view write this
<td>
#(personlist.FirstOrDefault().Name)
</td>
Just put a
List<Person>
into the ViewBag and in the View cast it back to List
This is what i did and It worked...
C#
ViewBag.DisplaylList = listData;
javascript
var dispalyList= #Html.Raw(Json.Encode(this.ViewBag.DisplaylList));
for(var i=0;i<dispalyList.length; i++){
var row = dispalyList[i];
..............
..............
}
//controller You can use this way
public ActionResult Index()
{
List<Fund> fundList = db.Funds.ToList();
ViewBag.Funds = fundList;
return View();
}
<--View ; You can use this way html-->
#foreach (var item in (List<Fund>)ViewBag.Funds)
{
<p>#item.firtname</p>
}
I had the problem that I wanted to use my ViewBag to send a list of elements through a RenderPartial as the object, and to this you have to do the cast first, I had to cast the ViewBag in the controller and in the View too.
In the Controller:
ViewBag.visitList = (List<CLIENTES_VIP_DB.VISITAS.VISITA>)
visitaRepo.ObtenerLista().Where(m => m.Id_Contacto == id).ToList()
In the View:
List<CLIENTES_VIP_DB.VISITAS.VISITA> VisitaList = (List<CLIENTES_VIP_DB.VISITAS.VISITA>)ViewBag.visitList ;

Resources