System.Web.Mvc.HtmlHelper<dynamic> exception on Html.PagedListPager - asp.net

When im trying to use my aspx file
#using PagedList.Mvc;
...
#Html.PagedListPager(ViewBag.test, page => Url.Action("Test", new { page })).
I'll get this error message
'System.Web.Mvc.HtmlHelper<dynamic>' has no applicable method named 'PagedListPager' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
My .cs file the code look like this
using PagedList;
private List<Quality> Qualitys()
{
List<Quality> Qualitys = new List<Quality>()
{
new Quality(){ID=1,Name="All Qualitys"},
new Quality(){ID=2,Name="1"},
new Quality(){ID=3,Name="2"},
new Quality(){ID=4,Name="3"},
new Quality(){ID=5,Name="4"},
new Quality(){ID=6,Name="5"}
};
return Qualitys;
}
public ActionResult Test(int? page)
{
int pageSize = 3;
int pageNumber = page ?? 1;
ViewBag.test = Qualitys().ToPagedList(pageNumber, pageSize);
return View();
}
In my ~Views/Web.config file I'll have there.
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="Web" />
</namespaces>
I cant see why Im getting this error, please help.

You need to cast dynamic properties (in this case ViewBag.test) to the required type. it should be
#Html.PagedListPager((IPagedList)ViewBag.test, page => Url.Action("Test", new { page }))

Related

Get UserId in MVC to use in View

I have the following problem in my MVC 5 web app. I used database first approach and the entity framwork to create a table [accountlist] that has a foreign key relationship on [UserId] to the [Id] column from [AspNetUsers]. Right now the pertaining accountlist.cshtml contains a dropdown menu. I also tried #Html.HiddenFor(model => model.UserId, new { #Value = HttpContext.Current.User.Identity.Name}) but the problem is how that I need the correct userid and not the username (I don't want the [UserName] from [AspNetUsers] to be an primary key).
Unfortunately, HttpContext.Current.User.Identity.GetUserId() as suggested in this solution says that Identity contains no definition for GetUserId().
Does anyone has solution?
Thanks in advance!
#stephen.vakil is correct. You need to import the namespace. Specifically, you need to add:
#using Microsoft.AspNet.Identity
#model Namespace.To.Foo
Alternatively, if you want to do this more often or just don't want to include the namespace in the view, you can edit the Web.config in the Views folder of your project and add it there instead:
<?xml version="1.0"?>
<configuration>
...
<system.web.webPages.razor>
...
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="Microsoft.AspNet.Identity" />
Any namespaces there are available to every view automatically.
this is the best Article for asp.net mvc authentication from ben foster. It helped me last time.
It works even if you are not going for entity framework
SigIn Like this
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Sid, userID)
},
"ApplicationCookie");
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignIn(identity);
Create New Class
public class AppUser : ClaimsPrincipal
{
public AppUser(ClaimsPrincipal principal)
: base(principal)
{
}
public int ID
{
get
{
return this.FindFirst(ClaimTypes.Sid).Value;
}
}
}
Let's create a custom base view page for our Razor views that provides access to our AppUser principal:
public abstract class AppViewPage<TModel> : WebViewPage<TModel>
{
protected AppUser CurrentUser
{
get
{
return new AppUser(this.User as ClaimsPrincipal);
}
}
}
public abstract class AppViewPage : AppViewPage<dynamic>
{
}
Open up /views/web.config and the set the pageBaseType:
<system.web.webPages.razor>
<pages pageBaseType="NakedIdentity.Mvc.AppViewPage">
Rebuild the project and update the Index.cshtml view:
<p>
User ID: #CurrentUser.ID?
</p>
If you are using SimpleMemberShip provider, then
int UserId = WebSecurity.CurrentUserId;
and add attribute [InitializeSimpleMembership] on the top of controller method.
add this line to your controller constructor:
user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
then you will have user.Id in all you methods inside your controller. And for security purpose, never keep your user id inside view as hidden!.

KendoUI Column Center Custom MVC Extension Method

I am looking for a way to create a custom extension method for a KendoUI column that will allow me to easily add a css class to the header or the cell itself using an extension method.
Right now i'm using the following to center the contents of both the header and the cell:
columns.Bound(x => x.Value).HeaderHtmlAttributes(new { #class = "cent" }).HtmlAttributes(new { #class = "cent" });
where the cent css class is:
.cent { text-align:center; }
To me this seems like alot of code to write for something this simple.
What i am looking for is a solution to create a custom column builder extension method where i can just do something like this:
columns.Bound(x => x.Value).CenterHeader().CenterCell();
Where the CenterHeader() and CenterCell() would be custom extension methods that would add this css class to the header and cell respectively. The code would look much cleaner if this were possible IMO.
Does anyone know a way to do this?
Why not just create these extensions?
using Kendo.Mvc.UI.Fluent;
namespace MyNamespace
{
public static class MyExtensions
{
public static GridTemplateColumnBuilder<T> CenterHeader<T>(this GridTemplateColumnBuilder<T> builder) where T : class
{
return builder.HeaderHtmlAttributes(new { #class = "cent" });
}
.....
}
}
And add this namespace (so that you shouldn't import it all the time) in Views/web.config:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
......
<add namespace="Kendo.Mvc.UI"/>
<add namespace="MyNamespace"/>
......
</namespaces>
</pages>
</system.web.webPages.razor>

MVC Easy util in view?

I am using asp.net MVC 4, I'd like to do something like this in my view
my link
I don't like it. Is there a way I can have the namespace implicit? Can I not pass in Viewbag and grab it somehow like global.request.current.viewbag?
If it helps I don't need TheFunctionIUseAlot to be static. I just need it to be easily callable in all my views and hopefully i'd like to not pass in viewbag. The reason I pass viewbag is because i need something in the controller which i stuck in viewbag as well. Maybe i can put it in the model but i don't want the same problem where i am passing model instead of viewbag
You can make the namespace implicit by adding #using NamespaceHere; at the top of your view, or by registering it as a namespace in the views web config. Something like this:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="NamespaceHere"/>
</namespaces>
</pages>
</system.web.webPages.razor>
You can get access to the viewbag in your function if you use a custom page base type for your views. You can find instructions on doing that here: http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx.
In your situation, to get access to the ViewBag you will want to define your FunctionThatIUseALot in a non-static class that takes a WebViewPage as a constructor parameter (either as dynamic or as a ViewDataDictionary). Then, in your WebViewPage's InitHelpers override, you can create your helper class, passing in this. That will give you access to all of the standard properties of the WebViewPage.
Something like this:
public class Utils {
private WebViewPage page;
public Utils(WebViewPage page) { this.page = page; }
public FunctionThatIUseALot(string someParameter) {
string someViewBagValue = page.ViewBag.SomeViewBagValue;
}
}
public abstract class CustomWebViewPage : WebViewPage {
public Utils Utils { get; set; } // Utils is your helper class
public override void InitHelpers() {
base.InitHelpers();
Utils = new Utils(this);
}
}
The above is not everything you need to do to make it work, you will need to read the article for the rest. But the end result should be that you can just call #Utils.FunctionThatIUseALot("some value") directly in your views.
Note: you will need to do this twice - once for the standard WebViewPage base class, and one for the WebViewPage<TModel> base class.

Why is my HttpHandler not being fired?

I am trying to use a http hadler, so I created a class lirary project and added this code:
namespace MyProject.Handlers
{
public class Class1 : IHttpHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.Write("Hello from custom handler.");
}
}
}
Then I compiled it and it generated the MyProject.Handlers.dll file. I put it in my asp.net bin folder and added this to the asp.net
<system.webServer>
<handlers>
<add name="TutorialHandler" verb="*" path="*" type="MyProject.Handlers.Class1, MyProject.Handlers" modules="IsapiModule" scriptProcessor="c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="File" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
//some stuff I *think* it doesn't make a difference
</modules>
//some stuff I *think* it doesn't make a difference
</system.webServer>
and
<system.web>
<httpHandlers>
<add verb="*" path="*" type="MyProject.Handlers.Class1, MyProject.Handlers" />
</httpHandlers>
</system.web>
But it just doesn't get called!
I start the debugger, set the breakpoint, but it doesn't stop. If I check the output html in firebug, the sentence "Hello from custom handler" is not there.
What am I doing wrong?
Thanks,
Oscar
EDIT: I'm using framework 4.0, IIS7.
Could it be that I am using routes? (not calling directly index.aspx, but /home or something like this?)
For some reason it wasn't being called when it was at the end of the handlers list. I moved to the top and got a strange error regarding webresources.axd. The reson was the path="*".
I couldn't find a matching path because I am using routes.
At the end I found out that I was using the wrong tool: the modules were the right thing for me, not handlers, because I would like to add things to my output depending on the case. So I changed my approach to use modules instead and it now looks good.
Thanks to all that helped me with comments!

IIS 7 Force Fresh Images

How do I force IIS 7 to not cache images for a particular page?
I would have thought that it is your browser doing the caching.
In any case one way around this as long as your link is not statically declared in the html, is to append a random number on the end of the images url:
<img src="http://mywebsite/images/mypic.png?a=123456" />
the argument means nothing because you are doing nothing with it, but to the browser it looks like a new uncached link.
How you put that random number on the end is up to you:
<img src="javascript:getMyLink();" />
or from the code behind:
Image myImage = new Image();
myImage.Source = "myurl?a=" + Guid.NewGuid().ToString();
someOtherControl.Controls.Add(myImage);
(of course this is pseudo code, you need to check that the property names are correct).
In IIS7, you can do this either declaratively in your web.config, or programmatically.
<location path="YourPath">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
</system.webServer>
</location>
The programmatic solution requires a simple HttpModule that's registered to run for all requests in Integrated mode, where you look for the URLs that you're concerned about. Then call:
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
FWIW, you may want to consider disabling client-side caching only, while enabling server-side caching, by using HttpCacheability.ServerAndNoCache. Also, if you add a query string on the image names, you will prevent server-side caching by http.sys.
In case it helps, I cover techniques like these in detail in my book: Ultra-Fast ASP.NET.
I've had to deal with this a lot but i need to better understand your end goal as IIS7 will update it's cache if an image is changed on the server, so maybe what you are seeing is the browser cache, have you looked into etags?
The old fall back is to stick a random query string at the end of the image path which keeps the browser guessing.
One sure way to prevent it from caching is to make custom file handler for .gif, .jpg, .png extention (lookup iHttpHandler) (code below lifted from http://www.codeguru.com/csharp/csharp/cs_network/http/article.php/c12641/
using System.IO;
using System.Web;
using System.Globalization;
namespace MVPHacks
{
public class ImageHandler: IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext ctx)
{
HttpRequest req = ctx.Request;
string path = req.PhysicalPath;
string extension = null;
string contentType = null;
extension = Path.GetExtension(path).ToLower();
switch (extension)
{
case ".gif":
contentType = "image/gif";
break;
case ".jpg":
contentType = "image/jpeg";
break;
case ".png":
contentType = "image/png";
break;
default:
throw new NotSupportedException("Unrecognized image type.");
} if (!File.Exists (path))
{
ctx.Response.Status = "Image not found";
ctx.Response.StatusCode = 404;
}
else
{
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = contentType;
ctx.Response.WriteFile (path);
}
}
public bool IsReusable { get {return true; } }
}
}
And don't forget to remove the default image handlers and add your in both sections of the web.config
<httpHandlers>
<clear />
<add verb="*" path="*.jpg" type="MVPHacks.ImageHandler" />
<add verb="*" path="*.gif" type="MVPHacks.ImageHandler" />
<add verb="*" path="*.png" type="MVPHacks.ImageHandler" />
</httpHandlers>
<handlers>
<clear />
<add verb="*" path="*.png" type="MVPHacks.ImageHandler" name="png" />
<add verb="*" path="*.gif" type="MVPHacks.ImageHandler" name="gif" />
<add verb="*" path="*.jpg" type="MVPHacks.ImageHandler" name="jpg />
</handlers>

Resources