jQuery Print Plugin

https://github.com/DoersGuild/jQuery.print

 

jQuery.print is a plugin for printing specific parts of a page

Usage

Include it in your HTML after importing jQuery, like:

    <script type="text/JavaScript" src="path/to/jquery.print.js" />

Use it like:

    $("#myElementId").print(/*options*/);

or

    $.print("#myElementId" /*, options*/);

You can submit the options object like:

    $("#myElementId").print({
            globalStyles: true,
            mediaPrint: false,
            stylesheet: null,
            noPrintSelector: ".no-print",
            iframe: true,
            append: null,
            prepend: null,
            manuallyCopyFormValues: true,
            deferred: $.Deferred(),
            timeout: 250,
                title: null,
                doctype: '<!doctype html>'
    });

Currently this plugin supports the following options:

globalStyles

  • Default: true
  • Acceptable-Values: Boolean
  • Function: Whether or not the styles from the parent document should be included

mediaPrint

  • Default: false
  • Acceptable-Values: Boolean
  • Function: Whether or not link tags with media=’print’ should be included; Over-riden by the globalStyles option

stylesheet

  • Default: null
  • Acceptable-Values: URL-string
  • Function: URL of an external stylesheet to be included

noPrintSelector

  • Default: ".no-print"
  • Acceptable-Values: Any valid jQuery-selector
  • Function: A selector for the items that are to be excluded from printing

iframe

  • Default: true, creates a hidden iframe if no-vaild iframe selector is passed
  • Acceptable-Values: Any valid jQuery-selector or Boolean
  • Function: Whether to print from an iframe instead of a pop-up window; can take the jQuery-selector of an existing iframe as value

append/prepend

  • Default: null
  • Acceptable-Values: Any valid jQuery-selector or HTML-text
  • Function: Adds custom HTML before (prepend) or after (append) the selected content

manuallyCopyFormValues

  • Default: true
  • Acceptable-Values: Boolean
  • Function: Should it copy user-updated form input values onto the printed markup (this is done by manually iterating over each form element)

deferred

  • Default: $.Deferred()
  • Acceptable-Values: Any valid jQuery.Deferred object
  • Function: A jQuery.Deferred object that is resolved once the print function is called

timeout

  • Default: 250
  • Acceptable-Values: Time in Milliseconds for setTimeout
  • Function: To change the amount of time to wait for the content, etc to load before printing the element from the new window/iframe created

title

  • Default: null, uses the host page title
  • Acceptable-Values: Any single-line string
  • Function: To change the printed title

doctype

  • Default: '<!doctype html>'
  • Acceptable-Values: Any valid doctype string
  • Function: To prepend a doctype to the printed document frame

Tested with

jQuery

Browsers

  • Google Chrome – v 20, 26, 48
  • Internet Explorer – v 10, 11
  • Firefox – v 35

Print Contents of HTML DIV control with Print Preview using jQuery

<head>
    <title></title>
   
        $(“#btnPrint”).live(“click”, function () {
            var divContents = $(“#dvContainer”).html();
            var printWindow = window.open(”, ”, ‘height=400,width=800’);
            printWindow.document.write(‘DIV Contents’);
            printWindow.document.write(”);
            printWindow.document.write(divContents);
            printWindow.document.write(”);
            printWindow.document.close();
            printWindow.print();
        });
   
</head>
<body>
    <form id=”form1″>
   

        This content needs to be printed.
   
    <input type=”button” value=”Print Div Contents” id=”btnPrint” />
    </form>
</body>
</html>

Common Shared Assembly

Snippet

using System.Reflection;
 
// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyCompany("123 Money Ltd.")]
[assembly: AssemblyCopyright("Copyright © 123 Money Ltd. 21016")]
[assembly: AssemblyTrademark("123 Money Ltd. t/a 123.ie")]
 
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Customize Rest Error Message with codes

public class NotFoundWithMessageResult : IHttpActionResult
{
    private string message;

    public NotFoundWithMessageResult(string message)
    {
        this.message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(message);
        return Task.FromResult(response);
    }
}

ASP.NET Web API CacheOutput

https://github.com/filipw/AspNetWebApi-OutputCache

 

ASP.NET Web API CacheOutput

A small library bringing caching options, similar to MVC’s “OutputCacheAttribute”, to Web API actions.

CacheOutput will take care of server side caching and set the appropriate client side (response) headers for you.

You can specify the following properties:

  • ClientTimeSpan (corresponds to CacheControl MaxAge HTTP header)
  • MustRevalidate (corresponds to MustRevalidate HTTP header – indicates whether the origin server requires revalidation of a cache entry on any subsequent use when the cache entry becomes stale)
  • ExcludeQueryStringFromCacheKey (do not vary cache by querystring values)
  • ServerTimeSpan (time how long the response should be cached on the server side)
  • AnonymousOnly (cache enabled only for requests when Thread.CurrentPrincipal is not set)

Additionally, the library is setting ETags for you, and keeping them unchanged for the duration of the caching period. Caching by default can only be applied to GET actions.

Installation

You can build from the source here, or you can install the Nuget version:

For Web API 2 (.NET 4.5)

PM> Install-Package Strathweb.CacheOutput.WebApi2

For Web API 1 (.NET 4.0)

PM> Install-Package Strathweb.CacheOutput

Usage

//Cache for 100 seconds on the server, inform the client that response is valid for 100 seconds
    [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

//Cache for 100 seconds on the server, inform the client that response is valid for 100 seconds. Cache for anonymous users only.
    [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100, AnonymousOnly = true)]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

//Inform the client that response is valid for 50 seconds. Force client to revalidate.
    [CacheOutput(ClientTimeSpan = 50, MustRevalidate = true)]
    public string Get(int id)
    {
        return "value";
    }

//Cache for 50 seconds on the server. Ignore querystring parameters when serving cached content.
    [CacheOutput(ServerTimeSpan = 50, ExcludeQueryStringFromCacheKey = true)]
    public string Get(int id)
    {
        return "value";
    }

Variations

CacheOutputUntil is used to cache data until a specific moment in time. This applies to both client and server.

//Cache until 01/25/2013 17:00
    [CacheOutputUntil(2013,01,25,17,00)]
    public string Get_until25012013_1700()
    {
        return "test";
    }

CacheOutputUntilToday is used to cache data until a specific hour later on the same day. This applies to both client and server.

//Cache until 23:55:00 today
    [CacheOutputUntilToday(23,55)]
    public string Get_until2355_today()
    {
        return "value";
    }

CacheOutputUntilThisMonth is used to cache data until a specific point later this month. This applies to both client and server.

//Cache until the 31st day of the current month
    [CacheOutputUntilThisMonth(31)]
    public string Get_until31_thismonth()
    {
        return "value";
    }

CacheOutputUntilThisYear is used to cache data until a specific point later this year. This applies to both client and server.

//Cache until the 31st of July this year
    [CacheOutputUntilThisYear(7,31)]
    public string Get_until731_thisyear()
    {
        return "value";
    }

Each of these can obviously be combined with the 5 general properties mentioned in the beginning.

Caching convention

In order to determine the expected content type of the response, CacheOutput will run Web APIs internal content negotiation process, based on the incoming request & the return type of the action on which caching is applied.

Each individual content type response is cached separately (so out of the box, you can expect the action to be cached as JSON and XML, if you introduce more formatters, those will be cached as well).

Important: We use action name as part of the key. Therefore it is necessary that action names are unique inside the controller – that’s the only way we can provide consistency.

So you either should use unique method names inside a single controller, or (if you really want to keep them the same names when overloading) you need to use ActionName attribute to provide uniqeness for caching. Example:

    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Team> Get()
    {
        return Teams;
    }

    [ActionName("GetById")]
    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Team> Get(int id)
    {
        return Teams;
    }

Ignoring caching

You can set up caching globally (add the caching filter to HttpConfiguration) or on controller level (decorate the controller with the cahcing attribute). This means that caching settings will cascade down to all the actions in your entire application (in the first case) or in the controller (in the second case).

You can still instruct a specific action to opt out from caching by using [IgnoreCacheOutput] attribute.

    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public class IgnoreController : ApiController
    {
        [Route("cached")]
        public string GetCached()
        {
            return DateTime.Now.ToString();
        }

        [IgnoreCacheOutput]
        [Route("uncached")]
        public string GetUnCached()
        {
            return DateTime.Now.ToString();
        }
    }

Server side caching

By default CacheOutput will use System.Runtime.Caching.MemoryCache to cache on the server side. However, you are free to swap this with anything else (static Dictionary, Memcached, Redis, whatever..) as long as you implement the followingIApiOutputCache interface (part of the distributed assembly).

public interface IApiOutputCache
{
    T Get<T>(string key) where T : class;
    object Get(string key);
    void Remove(string key);
    void RemoveStartsWith(string key);
    bool Contains(string key);
    void Add(string key, object o, DateTimeOffset expiration, string dependsOnKey = null);
}

Suppose you have a custom implementation:

public class MyCache : IApiOutputCache {
  //omitted for brevity
}

You can register your implementation using a handy GlobalConfiguration extension method:

//instance
configuration.CacheOutputConfiguration().RegisterCacheOutputProvider(() => new MyCache());

//singleton
var cache = new MyCache();
configuration.CacheOutputConfiguration().RegisterCacheOutputProvider(() => cache);  

If you prefer CacheOutput to use resolve the cache implementation directly from your dependency injection provider, that’s also possible. Simply register your IApiOutputCache implementation in your Web API DI and that’s it. WheneverCacheOutput does not find an implementation in the GlobalConiguration, it will fall back to the DI resolver. Example (using Autofac for Web API):

cache = new MyCache();
var builder = new ContainerBuilder();
builder.RegisterInstance(cache);
config.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build());

If no implementation is available in neither GlobalConfiguration or DependencyResolver, we will default toSystem.Runtime.Caching.MemoryCache.

Each method can be cached multiple times separately – based on the representation (JSON, XML and so on). Therefore,CacheOutput will pass dependsOnKey value (which happens to be a prefix of all variations of a given cached method) when adding items to cache – this gives us flexibility to easily remove all variations of the cached method when we want to clear the cache. When cache gets invalidated, we will call RemoveStartsWith and just pass that key.

The default cache store, System.Runtime.Caching.MemoryCache supports dependencies between cache items, so it’s enough to just remove the main one, and all sub-dependencies get flushed. However, if you change the defalt implementation, and your underlying store doesn’t – it’s not a problem. When we invalidate cache (and need to cascade through all dependencies), we call RemoveStartsWith – so your custom store will just have to iterate through the entire store in the implementation of this method and remove all items with the prefix passed.

Cache invalidation

There are three ways to invalidate cache:

  • [AutoInvalidateCacheOutput] – on the controller level (through an attribute)
  • [InvalidateCacheOutput(“ActionName”)] – on the action level (through an attribute)
  • Manually – inside the action body

Example:

[AutoInvalidateCacheOutput]
public class Teams2Controller : ApiController
{
    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Team> Get()
    {
        return Teams;
    }

    public void Post(Team value)
    {
        //do stuff
    }
}

Decorating the controller with [AutoInvalidateCacheOutput] will automatically flush all cached GET data from this controller after a successfull POST/PUT/DELETE request.

You can also use the [AutoInvalidateCacheOutput(TryMatchType = true)] variation. This will only invalidate such GETrequests that return the same Type or IEnumerable of Type as the action peformed takes as input parameter.

For example:

[AutoInvalidateCacheOutput(TryMatchType = true)]
public class TeamsController : ApiController
{
    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Team> Get()
    {
        return Teams;
    }

    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Player> GetTeamPlayers(int id)
    {
        //return something
    }

    public void Post(Team value)
    {
        //this will only invalidate Get, not GetTeamPlayers since TryMatchType is enabled
    }
}

Invalidation on action level is similar – done through attributes. For example:

public class TeamsController : ApiController
{
    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Team> Get()
    {
        return Teams;
    }

    [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
    public IEnumerable<Player> GetTeamPlayers(int id)
    {
        //return something
    }

    [InvalidateCacheOutput("Get")]
    public void Post(Team value)
    {
        //this invalidates Get action cache
    }
}

Obviously, multiple attributes are supported. You can also invalidate methods from separate controller:

    [InvalidateCacheOutput("Get", typeof(OtherController))] //this will invalidate Get in a different controller
    [InvalidateCacheOutput("Get")] //this will invalidate Get in this controller
    public void Post(Team value)
    {
        //do stuff
    }

Finally, you can also invalidate manually. For example:

    public void Put(int id, Team value)
    {
        //do stuff, update resource etc.

        //now get cache instance
        var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request);

        //and invalidate cache for method "Get" of "TeamsController"
        cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey((TeamsController t) => t.Get()));
    }

As you see, you can we use expression try to allow you to point to the method in a strongly typed way (we can’t unfortunately do that in the attributes, since C# doesn’t support lambdas/expression trees in attributes).

If your method takes in arguments, you can pass whatever – we only use the expression tree to get the name of the controller and the name of the action – and we invalidate all variations.

You can also point to the method in a traditional way:

        cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey("TeamsController","Get"));

Customizing the cache keys

You can provide your own cache key generator. To do this, you need to implement the ICacheKeyGenerator interface. The default implementation should suffice in most situations.

When implementing, it is easiest to inherit your custom generator from the DefaultCacheKeyGenerator class.

To set your custom implementation as the default, you can do one of these things:

// Method A: register directly
Configuration.CacheOutputConfiguration().RegisterDefaultCacheKeyGeneratorProvider(() => new CustomCacheKeyGenerator());

// Method B: register for DI (AutoFac example, the key is to register it as the default ICacheKeyGenerator)
builder.RegisterInstance(new CustomCacheKeyGenerator()).As<ICacheKeyGenerator>(); // this will be default
builder.RegisterType<SuperNiceCacheKeyGenerator>(); // this will be available, and constructed using dependency injection

You can set a specific cache key generator for an action, using the CacheKeyGenerator property:

[CacheOutput(CacheKeyGenerator=typeof(SuperNiceCacheKeyGenerator))]

PS! If you need dependency injection in your custom cache key generator, register it with your DI as itself.

This works for unregistered generators if they have a parameterless constructor, or with dependency injection if they are registered with your DI.

Finding a matching cache key generator is done in this order:

  1. Internal registration using RegisterCacheKeyGeneratorProvider or RegisterDefaultCacheKeyGeneratorProvider.
  2. Dependency injection.
  3. Parameterless constructor of unregistered classes.
  4. DefaultCacheKeyGenerator

JSONP

We automatically exclude callback parameter from cache key to allow for smooth JSONP support.

So:

/api/something?abc=1&callback=jQuery1213

is cached as:

/api/something?abc=1

Position of the callback parameter does not matter.

Etags

For client side caching, in addition to MaxAge, we will issue Etags. You can use the Etag value to make a request with If-None-Match header. If the resource is still valid, server will then response with a 304 status code.

For example:

GET /api/myresource
Accept: application/json

Status Code: 200
Cache-Control: max-age=100
Content-Length: 24
Content-Type: application/json; charset=utf-8
Date: Fri, 25 Jan 2013 03:37:11 GMT
ETag: "5c479911-97b9-4b78-ae3e-d09db420d5ba"
Server: Microsoft-HTTPAPI/2.0

On the next request:

GET /api/myresource
Accept: application/json
If-None-Match: "5c479911-97b9-4b78-ae3e-d09db420d5ba"

Status Code: 304
Cache-Control: max-age=100
Content-Length: 0
Date: Fri, 25 Jan 2013 03:37:13 GMT
Server: Microsoft-HTTPAPI/2.0

License

Licensed under Apache v2. License included.