Obtain the current contents of the TextWriter stream - asp.net-mvc

I'm building a custom HtmlHelper for MVC. I'd like to allow the user to add a block of HTML that will be used with the helper. So, I'm planning on having something similar to the following in my view:
#using (Html.MyHelper())
{
// foo
}
The MyHelper helper method is defined similar to the following:
public static MyHelperWriter MyHelper(this HtmlHelper helper)
{
helper.ViewContext.Writer.Write(#"<span>");
return new MyHelperWriter(helper.ViewContext.Writer);
}
public class MyHelperWriter : IDisposable
{
private bool disposed;
public TextWriter Writer { get; set; }
public MyHelperWriter(TextWriter writer)
{
/// TODO: Modify the TextWriter stream
Writer = writer;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
this.disposed = true;
Writer.Write(#"</span>");
}
}
}
What I'd like to do is update the TextWriter stream to capture it and do something to the contents. I know I can flush the stream, but I may want to override the behavior.
If this cannot be done (and seems icky), is there a better way to accomplish this same thing?

Have you looked into delegated razor templates?

Related

In MVC, how do I get an instance of HtmlHelper from AjaxHelper?

I have a custom control in my MVC 5 project. At the end of it I want add on a Save button and a ValidationSummary (in the WriteSubmitControls method). A Validation Summary is built using an instance of a HtmlHelper. Seems like HtmlHelper and AjaxHelper should share a base class or interface, but they don't appear to.
How do I access an instance of HtmlHelper without passing it in?
public class MyCustomAjaxForm: IDisposable
{
private readonly MvcForm _ajaxForm;
public MyCustomAjaxForm(AjaxHelper ajaxHelper)
{
_ajaxForm = ajaxHelper.BeginForm("Save", "Contacts", routeValues, ajaxOptions);
}
private void WriteSubmitControls()
{
_writer.WriteLine("<button type='submit'>Save</button>");
// Output Validation Summary Here
}
public void Dispose()
{
WriteSubmitControls();
_ajaxForm.Dispose();
}
}
I think I found a solution, but not sure if it's the best way. I create a new instance of HtmlHelper using the ViewContext and ViewDataContainer from the AjaxHelper.
public class MyCustomAjaxForm: IDisposable
{
private readonly MvcForm _ajaxForm;
private readonly HtmlHelper _htmlHelper;
public MyCustomAjaxForm(AjaxHelper ajaxHelper)
{
_ajaxForm = ajaxHelper.BeginForm("Save", "Contacts", routeValues, ajaxOptions);
//create instance of HtmlHelper
_htmlHelper = new HtmlHelper(ajaxHelper.ViewContext, ajaxHelper.ViewDataContainer);
}
private void WriteSubmitControls()
{
_writer.WriteLine("<button type='submit'>Save</button>");
//output ValidationSummary using instance of HtmlHelper
_writer.WriteLine(_htmlHelper.ValidationSummary(true));
}
public void Dispose()
{
WriteSubmitControls();
_ajaxForm.Dispose();
}
}

ASP.NET MVC Html Helper

I try to create some Html Helpers which will have an opening tag and closing tag which will include other contents like the Html.BeginForm does.
For example in Razor we can use the Html.BeginForm helper which has the following syntax:
#using (Html.BeginForm())
{
}
This code will include the contents of curly brackets within a and . The only way that I solved opening and closing a tag with contents is by using two html helpers. I define two html helpers:
public static MvcHtmlString StartForm(this System.Web.Mvc.HtmlHelper helper)
{
return new MvcHtmlString("<form>");
}
public static MvcHtmlString EndForm(this System.Web.Mvc.HtmlHelper helper)
{
return new MvcHtmlString("</form>");
}
Then I use the helpers using the following example:
#Html.StartForm()
contents
#Html.EndForm()
But I would like to be able to make one html helper which will have the following format in the view:
#using (Html.MyForm())
{
<text>contents</text>
}
Can someone help me with this problem because I do not know even how to search it.
You can define a class just like the way the MvcForm is implemented. The class below allows you to create a tag which contains other elements.
public class MvcTag : IDisposable
{
private string _tag;
private bool _disposed;
private readonly FormContext _originalFormContext;
private readonly ViewContext _viewContext;
private readonly TextWriter _writer;
public MvcTag(ViewContext viewContext, string tag)
{
if (viewContext == null)
{
throw new ArgumentNullException("viewContext");
}
_viewContext = viewContext;
_writer = viewContext.Writer;
_originalFormContext = viewContext.FormContext;
viewContext.FormContext = new FormContext();
_tag = tag;
Begin(); // opening the tag
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Begin()
{
_writer.Write("<" + _tag + ">");
}
private void End()
{
_writer.Write("</" + _tag + ">");
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
_disposed = true;
End(); // Closing the tag
if (_viewContext != null)
{
_viewContext.OutputClientValidation();
_viewContext.FormContext = _originalFormContext;
}
}
}
public void EndForm()
{
Dispose(true);
}
}
To make use of this MvcTag in the way the MvcForm is used, we have to define an extension
public static class HtmlHelperExtensions
{
public static MvcTag BeginTag(this HtmlHelper htmlHelper, string tag)
{
return new MvcTag(htmlHelper.ViewContext, tag);
}
}
And that's it. Now you can use it as:
#using(Html.BeginTag("div")) #* This creates a <div>, alternatively, you can create any tag with it ("span", "p" etc.) *#
{
<p>Contents</p>
}

How can I use same Ninject bindings in MVC and in my Models

I need to find a way to use Ninject in my classes (models) and also in my controllers of my MVC application.
How can I do to use the same bindings in both sides?
Right now I use my generated NinjectWebCommon.cs create my kernel and initialize the bootstrap:
private static void RegisterServices(IKernel kernel)
{
System.Web.Mvc.DependencyResolver.SetResolver(
new WebApplication1.Models.NinjectDependencyResolver(kernel)
);
}
My NinjectDependencyResolver looks like:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel k;
public NinjectDependencyResolver(IKernel kp)
{
this.k= kp;
AddBindings();
}
public object GetService(Type serviceType)
{
return k.Get(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return k.GetAll(serviceType);
}
private void AddBindings()
{
k.Bind<ISerializer>().To<MySerializer>();
}
}
MySerializer is my serialization class.
For my controllers, this part works fine.
But let's say I have the following model:
public class MyButton
{
ISerializer serializer;
public MyButton(ISerializer weapon)
{
serializer = weapon;
}
public string ToSString()
{
return serializer.serialize("my string - ");
}
}
How can I make Ninject work also for my model?
Thank you!
You may inject the model as well and add the following binding
private void AddBindings()
{
k.Bind<IMySerializer>().To<MySerializer>();
k.Bind<IModel>().To<Model>();
}
or if you are not injecting your model then you could do something like this thread says
using ninject to inject dependency to The Model classes or non-controller classes

How should Dispose be coded in classes that implement IDependencyResolver and IDependencyScope?

I ran Code Analysis on my Web API project, in which I'm trying to implement IoC and DI using Castle Windsor, and it found four problems. The four things it found were all in WindsorDependencyResolver, and all four are "Implement IDisposable correctly" namely:
0)
CA1063 Implement IDisposable correctly Provide an overridable implementation of Dispose(bool) on 'WindsorDependencyResolver' or mark the type as sealed. A call to Dispose(false) should only clean up native resources. A call to Dispose(true) should clean up both managed and native resources.
That points to this line of code:
public class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
1)
CA1063 Implement IDisposable correctly Modify 'WindsorDependencyResolver.Dispose()' so that it calls Dispose(true), then calls GC.SuppressFinalize on the current object instance ('this' or 'Me' in Visual Basic), and then returns.
That points to this line of code:
public void Dispose()
2) Same as O, but for the WindsorDependencyScope : IDependencyScope class.
3) Same as 1, but ""
I got the code I'm trying from Castle Windsor articles online, mainly from from this post. The entire code for this file is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
using Castle.Windsor;
using Castle.MicroKernel.Registration;
using System.Web.Http;
using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.SubSystems.Configuration;
using HandheldServer.Models;
namespace HandheldServer
{
public class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (!_container.Kernel.HasComponent(serviceType))
{
return new object[0];
}
return _container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
public class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
this._container = container;
this._scope = container.BeginScope();
}
public object GetService(Type serviceType)
{
if (_container.Kernel.HasComponent(serviceType))
{
return _container.Resolve(serviceType);
}
else
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this._container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
this._scope.Dispose();
}
}
public class ApiControllersInstaller : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly() // should it be Types instead of Classes?
.BasedOn<ApiController>()
.LifestylePerWebRequest());
}
}
// This idea from https://github.com/argeset/set-locale/blob/master/src/client/SetLocale.Client.Web/Configurations/IocConfig.cs
public class ServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IDeliveryItemRepository>().ImplementedBy<DeliveryItemRepository>().LifestylePerWebRequest(),
Component.For<IDeliveryRepository>().ImplementedBy<DeliveryRepository>().LifestylePerWebRequest(),
Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>().LifestylePerWebRequest(),
Component.For<IExpenseRepository>().ImplementedBy<ExpenseRepository>().LifestylePerWebRequest(),
Component.For<IInventoryItemRepository>().ImplementedBy<InventoryItemRepository>().LifestylePerWebRequest(),
Component.For<IInventoryRepository>().ImplementedBy<InventoryRepository>().LifestylePerWebRequest(),
Component.For<IItemGroupRepository>().ImplementedBy<ItemGroupRepository>().LifestylePerWebRequest());
}
}
}
What is the best way to mollify the Code Analysis tool?
Before answering your question please note that you should be very careful calling Dispose() on an object you didn't create and therefore are probably not responsible for. By this I mean the line
_container.Dispose();
the container was passed in so strictly speaking it is not yours to dispose of.
The easiest way to mollify the Code Analysis tool is to implement IDisposable as recommended
public class WindsorDependencyResolver
{
public WindsorDependencyResolver()
{
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed;
protected virtual void Dispose(bool disposing)
{
if (this.disposed) return;
if (disposing)
{
// call dispose on managed resources
// set to null
}
this.disposed = true;
}
}
See here for a thorough explanation of why, followed by many reasoned arguments as to why not! I would suggest that at the end of the day you should stick to your chosen standards and if that includes the code analysis tool then so be it.

how to hook ISmoothStreamCache object in SMFPlayer (Smooth Streaming Development kit)

I am using SMFPlayer in SilverLight Smooth Streaming Development Kit.
And I am able to play video content, however for some reason we want to have
control over data being downloaded and parsed. For that Purpose we want to start using
ISmoothStreamingCache interface.
I want to know what is the right approach to hook ISmoothStreamingCache object in SMFPlayer.
Thanks in advance
Big O
The ISmoothStreamingCache's implementation should also implement IPlugin interface. It should also be decorated with ExportAdaptiveCacheProvider attribute.
Then it will be automatically hooked to the SMFPlayer.
Below is skeleton code for class:
using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Net;
using Microsoft.SilverlightMediaFramework.Plugins;
using Microsoft.SilverlightMediaFramework.Plugins.Metadata;
using Microsoft.Web.Media.SmoothStreaming;
namespace MyNamespace
{
[ExportAdaptiveCacheProvider(PluginName = "My Smooth Streaming Cache")]
public class MySmoothStreamingCache : ISmoothStreamingCache, IPlugin
{
public MySmoothStreamingCache()
{
// Your implementation
}
#region ISmoothStreamingCache members
public IAsyncResult BeginRetrieve(CacheRequest request, AsyncCallback callback, object state)
{
// Your implementation
}
public CacheResponse EndRetrieve(IAsyncResult ar)
{
// Your implementation
}
public IAsyncResult BeginPersist(CacheRequest request, CacheResponse response, AsyncCallback callback, object state)
{
// Your implementation
}
public bool EndPersist(IAsyncResult ar)
{
// Your implementation
}
public void OpenMedia(Uri manifestUri)
{
// Your implementation
}
public void CloseMedia(Uri manifestUri)
{
// Your implementation
}
#endregion
#region IPlugin members
public bool IsLoaded { get; private set; }
public void Load()
{
IsLoaded = true;
}
public event Action<IPlugin, Microsoft.SilverlightMediaFramework.Plugins.Primitives.LogEntry> LogReady;
public event Action<IPlugin, Exception> PluginLoadFailed;
public event Action<IPlugin> PluginLoaded;
public event Action<IPlugin, Exception> PluginUnloadFailed;
public event Action<IPlugin> PluginUnloaded;
public void Unload()
{
IsLoaded = false;
}
#endregion
}
}

Resources