However, this doesn't operate in quite the same way. This solution works fine only if I'm loading media content that is directly connected to the current contextual item in the content tree. It throws an exception if you try and load content from somewhere else in the tree.
As an example, on my company page I have 'cards' with summary details for each team member on them. These cards then link to the actual team member page. Each team member has a small photo. Using the TypedMedia method call I can successfully load the image on the Team Member page itself but not in the summary partial on the main contact us page.
Sounds like you are not getting a collection correctly which contains the team members on the summary page. Could you possibly post your code for the partial view where you are getting the exception?
As a bit more info - In both scenarios if I debug down into the DocumentTypeBase class where I get the numeric value of the property both return the same value (1077). The error only occurs once I try and load the media with that ID value by calling MediaItem(1077) on the ContentRepository. I've put a catch trap around the error so I can return null, as you can see in the code above, but this is obviously not what I'm looking for.
Ok, this is a interesting approach to getting content for display. IContent is read/write but not cached at all so for getting and rendering content it is recommend that you use IPublishedContent and the methods on UmbracoHelper such as TypedContent, TypedMedia etc...
On this specific TypedMedia issue, what is the exception you are getting?
I am using the UmbracoHelper methods, I've simply wrapped them up in the ContentRepository. It allows me to put site specific stuff in there too, allows for greater separation of concerns and allows me to apply breaking changes across Umbraco upgrades with minimal pain. I think it's returning IPublishedContent or dynamics for pretty much everything now.
I get an 'Object Reference Not Set To An Instance Of An Object' (Null Reference Exception) but only when I try and load using Umbraco.TypedMedia(1077) from within my site's contact us (summary) or blog pages - the images load fine in the team member page itself. They are using the same model on all the pages so the code execution is exactly the same, as are the debug results until I call this method. I can only assume that there's something going on related to the Umbraco content tree's contextual position rather than just loading the media with the specified ID.
Prior to trying this I had it set up like this, which works fine (but is becoming obsolete)...
The Media Segment of the CONTENT REPOSITORY...
/// <summary>
/// Determines if a piece of media exists.
/// </summary>
/// <param name="mediaId">The media id.</param>
/// <returns></returns>
public bool MediaExists(int? mediaId)
{
return mediaId.HasValue && mediaId != 0 && MediaItem(mediaId) != null;
}
/// <summary>
/// Gets the media item.
/// </summary>
/// <param name="id">The id of the item.</param>
/// <returns></returns>
public IWrappedMedia MediaItem(int? id)
{
return id.HasValue ? new WrappedMedia(id.Value) : null;
}
/// <summary>
/// Gets the URL for some media content.
/// </summary>
/// <param name="mediaId">The media id.</param>
/// <returns>A nicely formed Url.</returns>
public string MediaUrl(int? mediaId)
{
// ReSharper disable once PossibleInvalidOperationException
return MediaExists(mediaId)
? MediaItem(mediaId.Value).Url
: String.Empty;
}
WrappedMedia is a class I created myself as, when I was last working on this U6 had just come out and there were still some odd issues around Media that blocked my unit testing. Here's the class..
WRAPPED MEDIA
using System;
using umbraco.cms.businesslogic.media;
namespace Ministry.Ministryweb.Models
{
/// <summary>
/// Wrapper class to enable testing around media items.
/// </summary>
public class WrappedMedia : IWrappedMedia
{
private readonly Media innerMedia;
/// <summary>
/// Initializes a new instance of the <see cref="WrappedMedia" /> class.
/// </summary>
/// <param name="id">The id.</param>
public WrappedMedia(int id)
{
innerMedia = id == 0 ? null : new Media(id);
Url = innerMedia != null
? innerMedia.getProperty(CommonProperties.UmbracoFile).Value.ToString()
: String.Empty;
}
public string Url { get; set; }
}
}
This allowed me to unit test with the old Media class and expose all I ever really care about, which is the actual path. I was hoping the TypedMedia(int id) method would effectively give me something similar via IPublishedContent and, aside from this slight snag, it seems to do just that.
Cool, so IContentRepository is not the Umbraco.Core.Persistence.Repositories one it's your own.
What version of Umbraco are you using? There were some bugs relating to exceptions being thrown when the id being passed in was an item in the recycle bin or deleted, is that a possibility?
The item in question in the example above are for profile pictures most of which have never been changed and certainly haven't been deleted. The item is definitely there, as evidenced if I switch back to the old method or if I view the Team Member page directly.
That's really strange, calling Umbraco.TypedMedia(1077) should always return the same regardless of where or when it's called, from what you are saying this is not the case?
OK - Here's the exception - I've commented out the dirty blind catch so it throws back up again. I'm not sure how much use this is without the actual Umbraco codebase behind it though...
Server Error in '/' Application.
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 121: //try
Line 122: //{
Line 123: return Umbraco.TypedMedia(id);
Line 124: //}
Line 125: //catch
Source File: c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Repositories\ContentRepository.cs Line: 123
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
Ministry.Ministryweb.Repositories.ContentRepository.MediaItem(Int32 id) in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Repositories\ContentRepository.cs:123
Ministry.Ministryweb.Models.TeamMember.BuildModel() in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Models\TeamMember.cs:103
Ministry.Ministryweb.Models.TeamMember..ctor(IPublishedContent content, IContentRepository contentRepo) in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Models\TeamMember.cs:64
Ministry.Ministryweb.Models.TeamMember..ctor(IPublishedContent content) in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Models\TeamMember.cs:51
CallSite.Target(Closure , CallSite , Type , Object ) +217
System.Dynamic.UpdateDelegates.UpdateAndExecute2(CallSite site, T0 arg0, T1 arg1) +974
Ministry.Ministryweb.Models.Article.GetAuthor() in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Models\Article.cs:106
Ministry.Ministryweb.Models.Article.get_Author() in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\Models\Article.cs:76
Ministry.Ministryweb.ViewModels.ArticleViewModel.get_AuthorUrl() in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministry.Ministryweb\ViewModels\ArticleViewModel.cs:41
ASP._Page_Views_Article_cshtml.Execute() in c:\Development\Projects\Ministryweb\ministryweb-azure\Ministryweb\Views\Article.cshtml:23
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +279
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +124
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +180
Umbraco.Core.Profiling.ProfilingView.Render(ViewContext viewContext, TextWriter writer) +139
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +379
System.Web.Mvc.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17() +32
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +613
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +613
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +263
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +720
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__19() +40
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +15
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
In certain cases I was using the wrong constructor on my Models which resulted in the UmbracoHelper instance within the ContentRepository being null. Dropping into the U7 codebase too allowed me to see the bug really quickly and get it resolved.
How to load Umbraco.Core.Models.Media by ID (part 2)
Earlier in the week I posted this...
I'm trying to remove some of my obsolete old code in a U6 solution I'm upgrading to U7.
I've got various references using the old Media object, created by passing in the ID. How do I do a similar thing in U7 with the new Media object?
I'm looking for something like MediaProvider.LoadMedia(int id) or similar.
Which appeared to have been solved by this...
Hello,
You can use Umbraco.TypedMedia(id). More info here: http://our.umbraco.org/documentation/Reference/Mvc/querying
Jeroen
However, this doesn't operate in quite the same way. This solution works fine only if I'm loading media content that is directly connected to the current contextual item in the content tree. It throws an exception if you try and load content from somewhere else in the tree.
As an example, on my company page I have 'cards' with summary details for each team member on them. These cards then link to the actual team member page. Each team member has a small photo. Using the TypedMedia method call I can successfully load the image on the Team Member page itself but not in the summary partial on the main contact us page.
Hi Keith,
Sounds like you are not getting a collection correctly which contains the team members on the summary page. Could you possibly post your code for the partial view where you are getting the exception?
Jeavon
CONTACT US (SUMMARY) VIEW...
VIEW PARTIAL...
MODEL CODE...
DOCUMENT TYPE BASE (This is inherrited by all of my models - the model code doesn't make much sense without it)
CONTENT REPOSITORY (This wraps the UmbracoHelper to allow for it to be unit tested (or it did before I upgraded to U7))...
As a bit more info - In both scenarios if I debug down into the DocumentTypeBase class where I get the numeric value of the property both return the same value (1077). The error only occurs once I try and load the media with that ID value by calling MediaItem(1077) on the ContentRepository. I've put a catch trap around the error so I can return null, as you can see in the code above, but this is obviously not what I'm looking for.
Ok, this is a interesting approach to getting content for display. IContent is read/write but not cached at all so for getting and rendering content it is recommend that you use IPublishedContent and the methods on UmbracoHelper such as TypedContent, TypedMedia etc...
On this specific TypedMedia issue, what is the exception you are getting?
I am using the UmbracoHelper methods, I've simply wrapped them up in the ContentRepository. It allows me to put site specific stuff in there too, allows for greater separation of concerns and allows me to apply breaking changes across Umbraco upgrades with minimal pain. I think it's returning IPublishedContent or dynamics for pretty much everything now.
I get an 'Object Reference Not Set To An Instance Of An Object' (Null Reference Exception) but only when I try and load using Umbraco.TypedMedia(1077) from within my site's contact us (summary) or blog pages - the images load fine in the team member page itself. They are using the same model on all the pages so the code execution is exactly the same, as are the debug results until I call this method. I can only assume that there's something going on related to the Umbraco content tree's contextual position rather than just loading the media with the specified ID.
Prior to trying this I had it set up like this, which works fine (but is becoming obsolete)...
The Media Segment of the CONTENT REPOSITORY...
WrappedMedia is a class I created myself as, when I was last working on this U6 had just come out and there were still some odd issues around Media that blocked my unit testing. Here's the class..
WRAPPED MEDIA
This allowed me to unit test with the old Media class and expose all I ever really care about, which is the actual path. I was hoping the TypedMedia(int id) method would effectively give me something similar via IPublishedContent and, aside from this slight snag, it seems to do just that.
Cool, so IContentRepository is not the Umbraco.Core.Persistence.Repositories one it's your own.
What version of Umbraco are you using? There were some bugs relating to exceptions being thrown when the id being passed in was an item in the recycle bin or deleted, is that a possibility?
Just upgraded to U7.0.4 from 6.?
The item in question in the example above are for profile pictures most of which have never been changed and certainly haven't been deleted. The item is definitely there, as evidenced if I switch back to the old method or if I view the Team Member page directly.
That's really strange, calling
Umbraco.TypedMedia(1077)
should always return the same regardless of where or when it's called, from what you are saying this is not the case?Could you post the whole exception?
OK - Here's the exception - I've commented out the dirty blind catch so it throws back up again. I'm not sure how much use this is without the actual Umbraco codebase behind it though...
Looking at the U7 Codebase itself, I notice that the Umbraco.TypedMedia() method is like this...
Could it be the ContentQuery that is null? I'm not sure where that's being set up.
Yeah, not a lot of clues in there. The value of id is 1077 when the exception occurs, right?
Indeed - Is there a way I can step through the Umbraco codebase without snarling up all my references and nuget packages?
You could clone the v7.0.4 and compile to get the PDB files or even attach to process https://github.com/umbraco/Umbraco-CMS/tree/7.0.4
And catch the call through with another instance of Visual Studio! Nice one - I'll give that a try when I get a chance.
Exactly :-)
Problem solved.
In certain cases I was using the wrong constructor on my Models which resulted in the UmbracoHelper instance within the ContentRepository being null. Dropping into the U7 codebase too allowed me to see the bug really quickly and get it resolved.
Thanks Jeavon!
Well done, that's awesome to hear!
This is what happens when you migrate code from U5 -> U4.11 -> U6 -> U7
Sometimes you just need to sweep out the cruft!
is working on a reply...