public static ConstructQueryString ( |
||
parameters | The parameters. | |
return | string |
/// <summary> /// Render HTML for a link /// </summary> /// <param name="link">The link to render</param> /// <param name="model">The model containing the link</param> /// <param name="field">An expression that points to the link</param> /// <param name="attributes">A collection of parameters to added to the link</param> /// <param name="isEditable">Indicate if the link should be editable in the page editor</param> /// <param name="contents">Content to go in the link</param> /// <returns>An "a" HTML element</returns> public virtual string RenderLink <T>(T model, Expression <Func <T, object> > field, object attributes = null, bool isEditable = false, string contents = null) { NameValueCollection attrs = null; if (attributes is NameValueCollection) { attrs = attributes as NameValueCollection; } else { attrs = Utilities.GetPropertiesCollection(attributes, true); } var sb = new StringBuilder(); var writer = new StringWriter(sb); var linkField = field.Compile().Invoke(model) as Fields.Link; RenderingResult result = null; if (IsInEditingMode && isEditable) { if (!string.IsNullOrEmpty(contents)) { attrs["haschildren"] = "true"; } if (contents.IsNotNullOrEmpty()) { attrs.Add("haschildren", "true"); } if (linkField != null) { AttributeCheck(attrs, "class", linkField.Class); AttributeCheck(attrs, "title", linkField.Title); } result = MakeEditable( field, null, model, Utilities.ConstructQueryString(attrs), _context, SitecoreContext.Database, writer); if (contents.IsNotNullOrEmpty()) { sb.Append(contents); } } else { result = BeginRenderLink( GetCompiled(field).Invoke(model) as Fields.Link, attrs, contents, writer ); } result.Dispose(); writer.Flush(); writer.Close(); return(sb.ToString()); }
/// <summary> /// Makes the editable. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="field">The field.</param> /// <param name="standardOutput">The standard output.</param> /// <param name="model">The model.</param> /// <param name="parameters">The parameters.</param> /// <returns>System.String.</returns> /// <exception cref="Glass.Mapper.MapperException"> /// To many parameters in linq expression {0}.Formatted(field.Body) /// or /// Expression doesn't evaluate to a member {0}.Formatted(field.Body) /// or /// Page editting error. Could not find property {0} on type {1}.Formatted(memberExpression.Member.Name, config.Type.FullName) /// or /// Page editting error. Could not find data handler for property {2} {0}.{1}.Formatted( /// prop.DeclaringType, prop.Name, prop.MemberType) /// </exception> /// <exception cref="System.NullReferenceException">Context cannot be null</exception> private RenderingResult MakeEditable <T>( Expression <Func <T, object> > field, Expression <Func <T, string> > standardOutput, T model, object parameters, Context context, Database database, TextWriter writer) { string firstPart = string.Empty; string lastPart = string.Empty; try { if (field == null) { throw new NullReferenceException("No field set"); } if (model == null) { throw new NullReferenceException("No model set"); } string parametersString = string.Empty; if (parameters == null) { parametersString = string.Empty; } else if (parameters is string) { parametersString = parameters as string; } else if (parameters is AbstractParameters) { parametersString = ((AbstractParameters)parameters).ToString(); } else if (parameters is NameValueCollection) { parametersString = Utilities.ConstructQueryString(parameters as NameValueCollection); } else { NameValueCollection attrs = Utilities.GetPropertiesCollection(parameters, true); parametersString = Utilities.ConstructQueryString(attrs); } if (IsInEditingMode) { if (field.Parameters.Count > 1) { throw new MapperException("To many parameters in linq expression {0}".Formatted(field.Body)); } MemberExpression memberExpression; if (field.Body is UnaryExpression) { memberExpression = ((UnaryExpression)field.Body).Operand as MemberExpression; } else if (!(field.Body is MemberExpression)) { throw new MapperException("Expression doesn't evaluate to a member {0}".Formatted(field.Body)); } else { memberExpression = (MemberExpression)field.Body; } //we have to deconstruct the lambda expression to find the //correct model object //For example if we have the lambda expression x =>x.Children.First().Content //we have to evaluate what the first Child object is, then evaluate the field to edit from there. //this contains the expression that will evaluate to the object containing the property var objectExpression = memberExpression.Expression; var finalTarget = Expression.Lambda(objectExpression, field.Parameters).Compile().DynamicInvoke(model); var site = global::Sitecore.Context.Site; if (context == null) { throw new NullReferenceException("Context cannot be null"); } var config = context.GetTypeConfiguration <SitecoreTypeConfiguration>(finalTarget); var scClass = config.ResolveItem(finalTarget, database); //lambda expression does not always return expected memberinfo when inheriting //c.f. http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo var prop = config.Type.GetProperty(memberExpression.Member.Name); //interfaces don't deal with inherited properties well if (prop == null && config.Type.IsInterface) { Func <Type, PropertyInfo> interfaceCheck = null; interfaceCheck = (inter) => { var interfaces = inter.GetInterfaces(); var properties = interfaces.Select(x => x.GetProperty(memberExpression.Member.Name)).Where( x => x != null); if (properties.Any()) { return(properties.First()); } else { return(interfaces.Select(x => interfaceCheck(x)).FirstOrDefault(x => x != null)); } }; prop = interfaceCheck(config.Type); } if (prop != null && prop.DeclaringType != prop.ReflectedType) { //properties mapped in data handlers are based on declaring type when field is inherited, make sure we match prop = prop.DeclaringType.GetProperty(prop.Name); } if (prop == null) { throw new MapperException( "Page editting error. Could not find property {0} on type {1}".Formatted( memberExpression.Member.Name, config.Type.FullName)); } //ME - changed this to work by name because properties on interfaces do not show up as declared types. var dataHandler = config.Properties.FirstOrDefault(x => x.PropertyInfo.Name == prop.Name); if (dataHandler == null) { throw new MapperException( "Page editting error. Could not find data handler for property {2} {0}.{1}".Formatted( prop.DeclaringType, prop.Name, prop.MemberType)); } using (new ContextItemSwitcher(scClass)) { RenderFieldArgs renderFieldArgs = new RenderFieldArgs(); renderFieldArgs.Item = scClass; var fieldConfig = (SitecoreFieldConfiguration)dataHandler; if (fieldConfig.FieldId != (Sitecore.Data.ID)null && fieldConfig.FieldId != ID.Null) { renderFieldArgs.FieldName = fieldConfig.FieldId.ToString(); } else { renderFieldArgs.FieldName = fieldConfig.FieldName; } renderFieldArgs.Parameters = WebUtil.ParseQueryString(parametersString ?? string.Empty); renderFieldArgs.DisableWebEdit = false; CorePipeline.Run("renderField", (PipelineArgs)renderFieldArgs); firstPart = renderFieldArgs.Result.FirstPart; lastPart = renderFieldArgs.Result.LastPart; } } else { if (standardOutput != null) { firstPart = standardOutput.Compile().Invoke(model); } else { var type = field.Body.Type; object target = (field.Compile().Invoke(model) ?? string.Empty); if (type == ImageType) { var image = target as Image; firstPart = RenderImage(image, WebUtil.ParseUrlParameters(parametersString)); } else if (type == LinkType) { var link = target as Link; var sb = new StringBuilder(); var linkWriter = new StringWriter(sb); var result = BeginRenderLink(link, WebUtil.ParseUrlParameters(parametersString), null, linkWriter); result.Dispose(); linkWriter.Flush(); linkWriter.Close(); firstPart = sb.ToString(); } else { firstPart = target.ToString(); } } } } catch (Exception ex) { firstPart = "<p>{0}</p><pre>{1}</pre>".Formatted(ex.Message, ex.StackTrace); Sitecore.Diagnostics.Log.Error("Failed to render field", ex, typeof(IGlassHtml)); } return(new RenderingResult(writer, firstPart, lastPart)); //return field.Compile().Invoke(model).ToString(); }