Testing image crops existence with Razor in Umbraco - image

I have created some Razor code to output images onto a page if the exist. It is detailed below and contains some simple checks to prevent rendering a blank list item. The site has gone live and works fine. The client then deleted the image from the media folder within Umbraco, meaning my node had a valid image assigned but the image just didn't exists. I got the following exception:
'string' does not contain a definition for 'crops'
How do I deal with this?
#using umbraco.MacroEngines;
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.presentation.nodeFactory
#using umbraco.cms.businesslogic.media
<ul>
#foreach (dynamic client in #Model.Children)
{
var image = Model.MediaById(client.Logo);
var crops = image.imageCropper.crops;
<li>
<h2><span>#client.Name</span></h2>
#if (crops != null || crops.GetType().ToString() != "System.String")
{
<span class="itemImage">
<img src="#crops.Find("#name", "cropname").url" alt="#client.Name" />
</span>
}
</li>
}
</ul>

In this case you'll probably need to do a type check. I believe the MediaById method should return a DynamicNode if it's valid, so something like the following should work:
if(image.GetType() == typeof(DynamicNode))
{
...
}

I was getting this issue. What I found is that the Model.MediaById(imageid) call would throw an exception if the Media had been deleted (and had already been picked in the past).
So I setup my test like this:
dynamic mainMediaImage = new DynamicNull();
try
{
mainMediaImage = Model.MediaById(related.eventMainImage);
}
catch(Exception e)
{
<p style='display: none;'>#e.Message</p>
}
var cropUrl = "";
if(mainMediaImage.GetType() == typeof(DynamicMedia))
{
cropUrl = GetImageCropperUrl(Model.MediaById(related.eventMainImage).crops, "List Image");
}
I still get the error, but it doesn't display to the user.
I found it would never get to my DynamicMedia check so I had to add the try...catch() around the call or else to entire Macro would fail.

Related

How can I check the URL path to apply a condition (Razor)

I am using code like this to detect the browser and apply a condition to display or not display <label>:
#{
var settings = Model.PartFieldDefinition.Settings.GetModel();
System.Web.HttpBrowserCapabilitiesBase theBrow = Request.Browser;
}
<fieldset>
#{
if ((theBrow.Browser == "IE") && (theBrow.MajorVersion < 10))
{
#:<label>#Model.DisplayName</label>
#://Some Code for inputs
}
else
{
#://Some Code for inputs
}
}
</fieldset>
I have been trying to figure out if I can (and if so, how) I could utilize this logic to detect what path in the website the user is in to display or not display <label>
For example, on any other path I want the label displayed. However, for the pages under ~/Services (the path), I want to be able to hide the label.
It's a little bit more complicated than that. The code is in an editor template that gets used all over the site. If I use CSS in the editor template to "hide" the label I will affect all the pages. I was hoping with the above logic I can avoid that and only apply my logic on certain pages under a path.
Thanks.
Update
I have tried the following:
#{
string CurrentURL = Request.ApplicationPath;
}
<fieldset>
#{
if ((CurrentURL == "Services")) // also tried "/Services"
// rest of code left out for brevity
}
but the labels are hidden on all pages, even outside the path "~/Services". Am stuck on the syntax.
Found answer
I did the following:
#{
string CurrentURL = Request.Url.AbsoluteUri;
}
<fieldset>
#{
if (CurrentURL.Contains("Services"))
}
and it worked. I don't know if anyone can comment, but which would be better to use: Request.Url.AbsoluteUri or Request.Url.ToString() (both of which work)?

How to perform click event on an element present in the anchor tag?

<div class="buttonClear_bottomRight">
<div class="buttonBlueOnWhite">
<a onclick="$find('{0}').close(true); callPostBackFromAlert();" href="#">Ok</a><div
class='rightImg'>
</div>
</div>
</div>
In the above code i wanted to click on Ok button present in the anchor tag.But an id is not generated because of which i cannot directly perform a click action. I tried a work around mentioned below.
IElementContainer elm_container = (IElementContainer)pw.Element(Find.ByClass(classname));
foreach (Element element in elm_container.Elements)
{
if (element.TagName.ToString().ToUpper() == "A")
{
element.Click();
}
}
But here elm_container returns null for intial instances due to which we cannot traverse through it. Is there any other easy method to do it ?
Try this...
Div div = browser.Div(Find.ByClass("buttonClear_bottomRight")).Div(Find.ByClass("buttonBlueOnWhite"));
Debug.Assert(div.Exists);
Link link = div.Link(lnk => lnk.GetAttributeValue("onclick").ToLower().Contains(".close(true)"));
Debug.Assert(link.Exists);
link.Click();
Hope it helps!
You can simply Click on the link by finding its text
var OkButton = Browser.Link(Find.ByText("Ok"));
if(!OkButton.Exists)
{
\\Log error here
}
OkButton.Click();
Browser.WaitForCompplete();
Or you can find the div containing the link like,
var ContainerDiv = Browser.Div(Find.ByClass("buttonBlueOnWhite"));
if(!ContainerDiv.Exists)
{
\\Log error here
}
ContainerDiv.Links.First().Click();
Browser.WaitForComplete();

How to use .trim().length in .cshtml page

I have written following condition in .cshtml page but it is not working
#if (row.item.FullName.Trim().length <= 0)
{
#Html.ActionLink("Create", "Create", "UsersInfo")
}
else
{
<a href='#Url.Action("Edit", "UsersInfo", new { id = row.item.UserId }))'>Contact</a>
}
My requirement is if FullName contains empty then link visible for Create else Edit. It is giving me following
Error:
System.NullReferenceException: Object reference not set to an instance
of an object.
if i use #if (row.item.FullName == "") then it will display following screen
<img src='http://www.codeproject.com/script/Membership/Uploads/5038017/screen.png'/>
Try String.IsNullOrEmpty(row.item.FullName).
Try this:
#if (String.IsNullOrEmpty(row.item.FullName))

Orchard - How to show more fields of a content item in a summery view

Let's say I have a product to which I've added an image field called SmallImage.
When I show a list of products, I want the small image to be in the view.
When I go to the list of divisions I get the default summary view, like so:
<article class="content-item #contentTypeClassName">
<header>
#Display(Model.Header)
#if (Model.Meta != null) {
<div class="metadata">
#Display(Model.Meta)
</div>
}
</header>
#Display(Model.Content)
#if(Model.Footer != null) {
<footer>
#Display(Model.Footer)
</footer>
}
</article>
How does #Display(Model.Content) generate the HTML?
Where is the .cshtml file I can put #Html.Image(Model.SmallImage) into?
EDIT
Ok, I found the property off the model: Model.ContentItem.Product.SmallImage.FileName, so I just need to know where the template file is.
THX!
Dan
Bonus Question:
Using the designer tools in any list view. Go to Zone[Content].Content.List. Under Shape is says there are two alternate views. One is MyTheme/Views/List.Html. If you click on "create" it says The relative virtual path 'Orchard.Core.Shapes.CoreShapes::List' is not allowed here. Does that mean that there really isn't an alternate for this view?
I manually created the file that was giving me the error in the bonus question and this gets me the image. (List-url-products.cshtml)
<div>
#foreach(var item in Model)
{
<div>#item.Title.ToString()</div>
var division = item.ContentItem.Division;
var smallImage = (Contrib.ImageField.Fields.ImageField) division.ListImage;
if(smallImage.FileName != null)
{
<div>#Html.Image(smallImage.FileName, null, new { Width=smallImage.Width, Height=smallImage.Height }) </div>
}
}
</div>

problem rendering image in browser FileContentResult

I want to show an image from database
I have an action
public FileContentResult GetImage(string param)
{
type obj = _someRepository.GetType(param);
if (obj!= null && obj.Image!= null)
{
return File(obj.Image.ToArray(), obj.Image.MimeType);
}
return "some default image";
}
in the view I have
< img src="<%:Url.Action("GetImage","ControllerName",new { param= somevalue })%>" alt="some text"
width="100px" height="100px" />
I also have
(Html.BeginForm("actionname", "controllername", FormMethod.Post, new { enctype = "multipart/form-data" })
set.
The image data is fetched from the database But I can't see the image in the browser,
is there something that I am missing?
Here are the steps I would perform in order to isolate the problem. Start with a simple controller action which returns some hardcoded image somewhere from your harddrive:
public ActionResult GetImage(string param)
{
byte[] image = File.ReadAllBytes(#"c:\work\foo.png");
return File(image, "image/png");
}
Now navigate directly to /ControllerName/GetImage in your browser and you should see the image.
The next step is to fetch the image from the database and probably store it on your harddisk to ensure that it is a valid image:
type obj = _someRepository.GetType(param);
File.WriteAllBytes(#"c:\work\foo.png", obj.Image.ToArray());
Now checkout the generated file and see if it is valid. The last step is to ensure that the url generated in the <img> tag is the same as the one you used to test directly. Then look at FireBug's Net tab to see if the browser correctly requests the image and what does the server return.
Most probably the issue is that the byte array returned from the database is not valid image or it is empty.
As far as the form you have shown in your question, this is for uploading files, it has nothing to do with serving dynamic images from a controller action, so I don't see what relation it might have to your question.

Resources