Can't Acces Configure Method in my Plugin - nopcommerce

I am developing a plugin in nopcommerce and uptill now i was able to get access Configure() method in my controller.
But suddenly I found i could not access my Configure() method and so not its view.
I have put debug point as well over there, but it doesn't hit so now, i don't understand how it happens without giving any error.
I have removed whatever code and changes I have done but still problem is not solved.
Can anyone help me?
Thanks in anticipation.

As Max suggested, it would be helpful if you are able to post your code for us to help troubleshoot.
In the mean time, please ensure that your route is set up properly in your Plugin's RouteProvider.cs. An example is at https://nopcommerce.codeplex.com/SourceControl/latest#src/Plugins/Nop.Plugin.DiscountRules.CustomerRoles/RouteProvider.cs
Please check to make sure that it matches your plugin's name/assembly's name/namespace etc. Its a good bet that one of those do not match up in your RouteProvider.

You have to add the GetConfigurationRoute method to your provider class like this:
public class XyzProvider : BasePlugin, IMiscPlugin
{
private readonly XyzObjectContext _context;
public XyzProvider(XyzObjectContext context)
{
_context = context;
}
public void GetConfigurationRoute(out string actionName, out string controllerName, out RouteValueDictionary routeValues)
{
actionName = "Configure";
controllerName = "Xyz";
routeValues = new RouteValueDictionary { { "Namespaces", "Nop.Plugin.Other.Xyz.Controllers" }, { "area", null } };
}

Related

HttpMediaTypeNotAcceptableException: Could not find acceptable representation. When with special url

#RequestMapping(value = "/servers/{domain}", method = RequestMethod.GET)
public Server getMailServer(#PathVariable("domain") String domain)
Server server = null;
try {
server = getServerByDomain(domain);
}
catch(Exception e){
}
return server;
}
When I call "http://localhost:8080/server/hotmail.com" with HttpClient Get method,the value of variable domain is "hotmail", not "hotmail.com".And I got the error:
HttpMediaTypeNotAcceptableException: Could not find acceptable representation.
But if I call "http://localhost:8080/server/hotmail", it works well.
I hope someone can see what is causing this issue.
This might be the same issue I had (and also this guy: https://stick2code.blogspot.co.at/2014/03/solved-orgspringframeworkwebhttpmediaty.html)
My service offers operations on files, i.e., /files/check/foo.txt
I always got a HttpMediaTypeNotAcceptableException and my rest handler was never actually called.
The problem is, that Spring has a feature where it tries to detect the requested content type by the path extension. So .com could mean a COM File. (See http://docs.spring.io/spring/docs/4.3.3.RELEASE/spring-framework-reference/htmlsingle/#mvc-config-content-negotiation and http://docs.spring.io/spring/docs/4.3.3.RELEASE/spring-framework-reference/htmlsingle/#mvc-config-path-matching)
My minimal #Config fix:
#Configuration
#EnableWebMvc
public class PathDispatchConfig extends WebMvcConfigurerAdapter {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
configurer.setUseRegisteredSuffixPatternMatch(false);
}
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
Change your #RequestMapping to following:)
#RequestMapping(value = "/servers/{domain:.+}", method = RequestMethod.GET)
I had the same problem because I had usernames (=mail adresses) in my request url. Thanks to the post of Benjamin Maurer I found the problem. However, I fixed it in a different way because I was unsure of the consequences regarding security of his answer.
I added the usernames as request parameters in the request. In your case, this would look something like:
#RequestMapping(value = "/servers", method = RequestMethod.GET)
public Server getMailServer(#RequestParam("domain") String domain) {
// do stuff
}
The request url would then look something like:
http://localhost:8080/server?domain=hotmail.com

Infinite URL Parameters for ASP.NET MVC Route

I need an implementation where I can get infinite parameters on my ASP.NET Controller. It will be better if I give you an example :
Let's assume that I will have following urls :
example.com/tag/poo/bar/poobar
example.com/tag/poo/bar/poobar/poo2/poo4
example.com/tag/poo/bar/poobar/poo89
As you can see, it will get infinite number of tags after example.com/tag/ and slash will be a delimiter here.
On the controller I would like to do this :
foreach(string item in paramaters) {
//this is one of the url paramaters
string poo = item;
}
Is there any known way to achieve this? How can I get reach the values from controller? With Dictionary<string, string> or List<string>?
NOTE :
The question is not well explained IMO but I tried my best to fit it.
in. Feel free to tweak it
Like this:
routes.MapRoute("Name", "tag/{*tags}", new { controller = ..., action = ... });
ActionResult MyAction(string tags) {
foreach(string tag in tags.Split("/")) {
...
}
}
The catch all will give you the raw string. If you want a more elegant way to handle the data, you could always use a custom route handler.
public class AllPathRouteHandler : MvcRouteHandler
{
private readonly string key;
public AllPathRouteHandler(string key)
{
this.key = key;
}
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var allPaths = requestContext.RouteData.Values[key] as string;
if (!string.IsNullOrEmpty(allPaths))
{
requestContext.RouteData.Values[key] = allPaths.Split('/');
}
return base.GetHttpHandler(requestContext);
}
}
Register the route handler.
routes.Add(new Route("tag/{*tags}",
new RouteValueDictionary(
new
{
controller = "Tag",
action = "Index",
}),
new AllPathRouteHandler("tags")));
Get the tags as a array in the controller.
public ActionResult Index(string[] tags)
{
// do something with tags
return View();
}
That's called catch-all:
tag/{*tags}
Just in case anyone is coming to this with MVC in .NET 4.0, you need to be careful where you define your routes. I was happily going to global.asax and adding routes as suggested in these answers (and in other tutorials) and getting nowhere. My routes all just defaulted to {controller}/{action}/{id}. Adding further segments to the URL gave me a 404 error. Then I discovered the RouteConfig.cs file in the App_Start folder. It turns out this file is called by global.asax in the Application_Start() method. So, in .NET 4.0, make sure you add your custom routes there. This article covers it beautifully.
in asp .net core you can use * in routing
for example
[HTTPGet({*id})]
this code can multi parameter or when using send string with slash use them to get all parameters

How to hide tabs based on roles defined in attributes in MVC3?

In a default install of a MVC3 website tabs are created in the top left. I would like to hide/show these tabs based on whether the current user would have access to the index ViewResult. The allowed roles to the ViewResult are defined by attributes. Is there any way of getting the list of roles for a ViewResult?
If you are asking (sorry, wasn't clear exactly to me) about conditional showing of HTML elements based on roles, you could do something like this:
#if (User.IsInRole("Administrators"))
{
#Html.ActionLink("Do Some Action", "DoAction", "SomeController")
}
If that isn't what you're asking, let me know.
Follow-up based on your comment:
Your question interests me and I did a little poking around and found that Vivien Chevallier has an interesting idea here which essentially lets you write something like so:
#Html.ActionLinkAuthorized("The Privilege Zone", "ThePrivilegeZone", "Home", true)
in your View and then this check the controller action and either renders a link or doesn't.
In his controller example, you've got an action like this:
[Authorize(Roles = "Administrator")]
public ActionResult ThePrivilegeZone()
{
return View();
}
(I guess the key point here is that your View doesn't know squat about "Administrators" and relies upon the extension code to do the heavy lifting here:
public static MvcHtmlString ActionLinkAuthorized(
this HtmlHelper htmlHelper,
string linkText, string actionName, string controllerName,
RouteValueDictionary routeValues,
IDictionary<string, object> htmlAttributes, bool showActionLinkAsDisabled)
{
if (htmlHelper.ActionAuthorized(actionName, controllerName))
{
return htmlHelper.ActionLink(
linkText,
actionName, controllerName, routeValues, htmlAttributes);
}
else
{
if (showActionLinkAsDisabled)
{
TagBuilder tagBuilder = new TagBuilder("span");
tagBuilder.InnerHtml = linkText;
return MvcHtmlString.Create(tagBuilder.ToString());
}
else
{
return MvcHtmlString.Empty;
}
}
}
Rather than cut/paste all of that code here, you can take a look at it and see the example application he's got for that. I think what's particularly interesting to this approach is that the view could display that PrivilegeZone link but knows only that something else will determine whether that's the case. So, assuming that you got new requirements to only allow folks who were "Administrators" or "Owners" to have access to the link, you could modify the controller action accordingly and not touch the view code. Interesting idea, at least to me.

System.Web.Routing with WebForms - picking up variables in the target page

I have the pattern User/{domain}/{username} set up via Routing. Everything works except for one thing. I can't figure out how to get the domain and username variables passed to my redirected page. Below is my GetHttpHandler method from my IRouteHandler implementation.
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string basePath;
basePath = "~/UserPage.aspx";
string domain = requestContext.RouteData.GetRequiredString("domain");
string username = requestContext.RouteData.GetRequiredString("username");
string virtualPath =
string.Format(basePath + "?domain={0}&username={1}", domain, username);
return (Page)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
}
I get the error from the last line of code:
UserPage.aspx?domain=SOMEDOMAIN&username=SOMEUSER is not a valid virtual path.
So how are you supposed to pass variables to the target page? what am I missing?
I think I solved this one myself.
Found this loop
foreach (KeyValuePair<string, object> token in requestContext.RouteData.Values)
{
requestContext.HttpContext.Items.Add(token.Key, token.Value);
}
from http://www.codethinked.com/post/2008/08/20/Exploring-SystemWebRouting.aspx
Its like the 4th code sample down.
UPDATE:
Not sure if this will work... requestContext.HttpContext seems to be "readonly". Back to the drawing board.
UPDATE 2:
Looks like this will work if you add in a reference to System.Web.Abstractions
Started mucking around with things and saw the IHttpHandler interface provides the RequestContext to the GetHttpHandler method.
So, I modified my base page class (I always put a layer between System.Web.UI.Page and my own pages, calling it BasePage or similar just for the purpose). So I added a public property on PVBasePage to receive a RequestContext object.
public RequestContext RequestContext { get; set; }
Then, my Routing class code is as follows:
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
// create the page object as my own page...
var page = BuildManager.CreateInstanceFromVirtualPath(VirtualPath
, typeof(PVBasePage)) as PVBasePage;
// pass in the request context
page.RequestContext = requestContext;
// return this page in the form of a IHttpHandler
return page as IHttpHandler;
}
So instead of, as in the sample code, creating the instance directly as the IHttpHandler, I create it as my own page. Set the request context property, and then return the page to the caller AS a IHttpHandler.
Tested and it works. WOO HOO!
Then in the instance page, you can hit the RequestContext.GetValues collection to read out your passed in parameters.
HTH
#B.Tyndall
I just got this working with a solution similar to yours.
found at: http://msmvps.com/blogs/luisabreu/archive/2008/03/12/using-the-routing-mvc-api-with-classic-asp-net.aspx
foreach (var aux in requestContext.RouteData.Values)
{
HttpContext.Current.Items[aux.Key] = aux.Value;
}
So in effect you're no longer using the Request.QueryString but instead Context.Items collection
HttpContext.Current.Items["RouteName"]
or
Context.Items["RouteName"]
It appears as though other are also taking the route (no pun intended) of putting the parameters in the context Items collection.
http://bbits.co.uk/blog/archive/2008/05/19/using-asp.net-routing-independent-of-mvc---passing-parameters-to.aspx
I combined a couple of these approaches for pages that have a specific parameter, I created a UserNameRouteHandler for pages that accept that type of parameter. In my PageBase class I checked the context items for that parameter and then set a property so that my pages that inherit from PageBase can use it.
public class UserNameRouteHandler : IRouteHandler
{
#region Implementation of IRouteHandler
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string pageName = requestContext.RouteData.GetRequiredString("PageName");
string employeeUserName = requestContext.RouteData.GetRequiredString("UserName");
if(!string.IsNullOrEmpty(employeeUserName))
{
requestContext.HttpContext.Items["UserName"] = employeeUserName;
}
pageName = pageName.ToLower() == "home" ? "default" : pageName;
string virtualPath = string.Format("~/{0}.aspx", pageName);
return (Page)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
}
#endregion
}
And in my OnLoad of PageBase I set the property to pages that need it can have it...definitely looking for a more elegant solution though.
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
if (Context.Items["UserName"] != null)
{
EmployeeUserName = Context.Items["UserName"].ToString();
}
}
base.OnLoad(e);
}

Mocking HttpContext doesn't work

I am trying to mock out HttpContext so that I can unit test my controller's Request.IsAuthenicated call. I am using the code that I found at Scott Hanselman's blog to simulate HttpContext using rhino.mocks.
so i have this unit test piece:
PostsController postsController = new PostsController(postDL);
mocks.SetFakeControllerContext(postsController);
Expect.Call(postsController.Request.IsAuthenticated).Return(true);
In my controller action, I have something like
if(Request.IsAuthenticated)....
when I try to run the unit test, the test fails throwing a null exception, and when I try to debug the unit test, I see that the HttpContext is never assigned to the controller.
any ideas?
This should work:
PostsController postsController = new PostsController(postDL);
var context = mocks.Stub<HttpContextBase>();
var request = mocks.Stub<HttpRequestBase>();
SetupResult.For(request.IsAuthenticated).Return(true);
SetupResult.For(context.Request).Return(request);
postsController.ControllerContext = new ControllerContext(context, new RouteData(), postsController);
This may be of some use to you, worked for me in a similar scenario:
http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx
You may find the post I wrote on this to be helpful in some way
http://santoshbenjamin.wordpress.com/2008/08/04/mock-httpcontext-and-session-state/
cheers
benjy
Now, for disclosure, I have yet to get my hands dirty with most of the stuff you are working with, however:
If you want to mock the IsAuthenticated, why not just create a static class to return a bool that can the be manipulated by your test code?
This is a bit rough round the edges, but hopefully you get the idea:
interface IAuthenticationChecker
{
bool IsAuthenticated { get; }
}
public class MockAuthenticationChecker : IAuthenticationChecker
{
static bool _authenticated = false;
public static void SetAuthenticated(bool value)
{
_authenticated = value;
}
#region IAuthenticationChecker Members
public bool IsAuthenticated
{
get { return _authenticated; }
}
#endregion
}
public class RequestAuthenticationChecker : IAuthenticationChecker
{
#region IAuthenticationChecker Members
public bool IsAuthenticated
{
get {
if (HttpContext.Current == null)
throw new ApplicationException(
"Unable to Retrieve IsAuthenticated for Request becuse there is no current HttpContext.");
return HttpContext.Current.Request.IsAuthenticated;
}
}
#endregion
}
You can then use a reference to either at app level, yeah it means you have to add a reference at app level, and you need to use a different ref rather than Request, but you also get complete control over the authentication for testing :)
FYI - this is totally open to being blown apart, I threw it together in about a minute :)
Here is one simple way to fake the context, found it from Jeff's blog :
TextWriter tw = new StringWriter();
HttpWorkerRequest wr = new SimpleWorkerRequest("/webapp", "c:\\inetpub\\wwwroot\\webapp\\", "default.aspx", "", tw);
HttpContext.Current = new HttpContext(wr);
Here's a class that may be useful. It handles ajax requests, user authentication, request parameters and more: https://gist.github.com/3004119

Resources