XmlSiteMapController parameterless public constructor - mvcsitemapprovider

I’m using the NuGet Package MvcSiteMapProvider MVC4. When I run MvcSiteMapProvider.Web.Mvc.XmlSiteMapController.RegisterRoutes(routes); using this method, I’m getting the following error when I run localhostXXX/sitemap.xml
[InvalidOperationException: An error occurred when trying to create a controller of type 'MvcSiteMapProvider.Web.Mvc.XmlSiteMapController'. Make sure that the controller has a parameterless public constructor.]
Ostensibly, MvcSiteMapProvider.Web.Mvc.IXmlSiteMapResultFactory xmlSiteMapResultFactory is null, but I don't know why (or frankly, what that means).
I've not messed with routes at all, but I have developed the site a bit. I created a custom version of the XmlSiteMapController and gave it the overloaded null XmlSiteMapController method to poke around, but I’m not familiar at all with IXmlSiteMapResultFactory and besides, why is it trying to call a null method in the first place? And just to cover bases, I have uninstalled and reinstalled MvcSiteMapProvider MVC4.
Works fine on all my other sites... any ideas?
EDIT***
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
MyAPI.Controllers.CustomXmlSiteMapController.RegisterRoutes(routes);
Then just made a blank controller (for tracing) in there:
public CustomXmlSiteMapController()
{
}
to go along with...
public CustomXmlSiteMapController(MvcSiteMapProvider.Web.Mvc.IXmlSiteMapResultFactory xmlSiteMapResultFactory)
{

Related

jHipster gateway downstream prefix

I'm updating old jHipster gateway to 7.5.0 version. New version uses Spring Cloud Gateway (with Eureka), while the old one used Zuul. In previous version working with Service Discovery having service named 'foo' and path 'bar' would register it without any prefix on the gateway so it could be accessed as:
GATEWAY_URL/foo/bar
right now all services register with 'services/' prefix which results requires to call following url:
GATEWAY_URL/services/foo/bar
I can't find configuration responsible for that. I found a property spring.webservices.path, but changing this to other value does not make any change and in Spring Boot 2.6.3 its value cannot be empty or '/' (but Im not sure if this is a property I should be checking). I also experimented with spring.cloud.gateway.routes in form:
spring:
webservices:
path: /test
main:
allow-bean-definition-overriding: true
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: user-service-route
uri: lb://user
predicates:
- Path=/user/**
but without any luck. Also Im not sure if this is jHipster issue or SCG
I need to change that so that other systems using my API won't need to update their paths, I know I can always add nginx before so that it will rewrite te path but that feels not correct.
This behavior is done by SCG autoconfiguration - GatewayDiscoveryClientAutoConfiguration, it registers DiscoveryLocatorProperties bean with predicate:
PredicateDefinition{name='Path', args={pattern='/'+serviceId+'/**'}}
I didnt want to change autoconfigration, so I did WebFilter that is executed as first one and mutates request path
public class ServicesFilter implements WebFilter {
private final ServicesMappingConfigration mapping;
public ServicesFilter(ServicesMappingConfigration mapping) {
this.mapping = mapping;
}
#Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
RequestPath path = exchange.getRequest().getPath();
if (path.elements().size() > 1) {
PathContainer pathContainer = path.subPath(1, 2);
if (mapping.getServices().contains(pathContainer.value())) {
ServerHttpRequest mutatedRequest = exchange
.getRequest()
.mutate()
.path("/services" + exchange.getRequest().getPath())
.build();
ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
return chain.filter(mutatedExchange);
}
}
return chain.filter(exchange);
}}

Trying to implement a custom route in umbraco 7.5.3 but the overrided method FindContent does not get fired

I've trying to retrieve the rendermodel model into my custom hijacked method, but i always get null. The two optional parameters are correct.
This is my custom route :
RouteTable.Routes.MapRoute(
"umbracoRoute",
"token-verification/{action}/{userId}/{code}",
new
{
controller = "ExternalLinkOperations",
action = "",
userId = UrlParameter.Optional,
code = UrlParameter.Optional
},
new ConfirmEmailRouteHandler(3290)
);
this is the ConfirmEmailRouteHandler class:
public class ConfirmEmailRouteHandler: UmbracoVirtualNodeByIdRouteHandler
{
public ConfirmEmailRouteHandler(int realNodeId) : base(realNodeId)
{
}
protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext, IPublishedContent baseContent)
{
return base.FindContent(requestContext, umbracoContext, baseContent);
}
}
and this is the the method in the ExternalLinkOperationsController which inherit from rendermodel:
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(RenderModel model, string userId, string code)
{}
so Im not getting the model parameter only the two optional parameter, what i could be doing wrong, I also tried to make this
new UmbracoVirtualNodeByIdRouteHandler(3290)
instead of
new ConfirmEmailRouteHandler(3290),
but without success, I'm using umbraco v 7.5.3. Debugging the code in any moment the overrided method FindContent gets fired, only when the constructor.
Thanks in advance for any help
I didn't realized the route property is incorrect, i have RouteTable.Routes.MapRoute, and i am supposed to be using RouteTable.Routes.MapUmbracoRoute
answer by Shannon Deminick here!

Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL

...guess I'm the first to ask about this one?
Say you have the following routes, each declared on a different controller:
[HttpGet, Route("sign-up/register", Order = 1)]
[HttpGet, Route("sign-up/{ticket}", Order = 2)]
... you could do this in MVC 5.0 with the same code except for the Order parameter. But after upgrading to MVC 5.1, you get the exception message in the question title:
Multiple controller types were found that match the URL. This can
happen if attribute routes on multiple controllers match the requested
URL.
So the new RouteAttribute.Order property is only controller-level? I know in AttributeRouting.NET you can do SitePrecedence too. Is the only way to have routes like the above when all actions are in the same controller?
Update
Sorry, I should have mentioned these routes are on MVC controllers, not WebAPI. I am not sure how this affects ApiControllers.
If you know that ticket will be an int you can specify that type in the route to help resolve the route:
[HttpGet, Route("sign-up/register")]
[HttpGet, Route("sign-up/{ticket:int}")]
This approach worked for me, per user1145404's comment that includes a link to Multiple Controller Types with same Route prefix ASP.NET Web Api
In case of Attribute routing, Web API tries to find all the controllers which match a request. If it sees that multiple controllers are able to handle this, then it throws an exception as it considers this to be possibly an user error. This route probing is different from regular routing where the first match wins.
As a workaround, if you have these two actions within the same controller, then Web API honors the route precedence and you should see your scenario working.
There are two ways to fix this:
A regex constraint, like here: MVC Route Attribute error on two different routes
Or a custom route constraint, like here: https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/
You can create custom route constraints by implementing the IRouteConstraint interface. For example, the following constraint restricts a parameter to set of valid values:
public class ValuesConstraint : IRouteConstraint
{
private readonly string[] validOptions;
public ValuesConstraint(string options)
{
validOptions = options.Split('|');
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase);
}
return false;
}
}
The following code shows how to register the constraint:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var constraintsResolver = new DefaultInlineConstraintResolver();
constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint));
routes.MapMvcAttributeRoutes(constraintsResolver);
}
}
Now you can apply the constraint in your routes:
public class TemperatureController : Controller
{
// eg: temp/celsius and /temp/fahrenheit but not /temp/kelvin
[Route("temp/{scale:values(celsius|fahrenheit)}")]
public ActionResult Show(string scale)
{
return Content("scale is " + scale);
}
}
In my opinion, this isn't great design. There are no judgments about what URL you intended and no specificity rules when matching unless you explicitly set them yourself. But at least you can get your URLs looking the way you want. Hopefully your constraint list isn't too long. If it is, or you don't want to hard-code the route string parameter and its constraints, you could build it programmatically outside the action method and feed it to the Route attribute as a variable.

Breeze & EFContextProvider - How to properly return $type when using expand()?

I am using Breeze with much success in my SPA, but seem to be stuck when trying to return parent->child data in a single query by using expand().
When doing a single table query, the $type in the JSON return is correct:
$type: MySPA.Models.Challenge, MySPA
However if I use expand() in my query I get the relational data, but the $type is this:
System.Collections.Generic.Dictionary 2[[System.String, mscorlib],[System.Object, mscorlib]]
Because of the $type is not the proper table + namespace, the client side code can't tell that this is an entity and exposes it as JSON and not a Breeze object (with observables, entityAspect, etc.).
At first I was using my own ContextProvider so that I could override the Before/After saving methods. When I had these problems, I reverted back to the stock EFContextProvider<>.
I am using EF5 in a database first mode.
Here's my controller code:
[BreezeController]
public class DataController : ApiController
{
// readonly ModelProvider _contextProvider = new ModelProvider();
readonly EFContextProvider<TestEntities> _contextProvider = new EFContextProvider<TestEntities>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
[HttpGet]
public IQueryable<Challenge> Challenges()
{
return _contextProvider.Context.Challenges;
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
public IQueryable<ChallengeNote> ChallengeNotes()
{
return _contextProvider.Context.ChallengeNotes;
}
}
Here's my BreezeWebApiConfig.cs
public static void RegisterBreezePreStart()
{
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "breeze/{controller}/{action}"
);
}
Is there a configuration setting that I am missing?
Did you try "expanding" on server side? Is it needed to do expand on client side? I tried to do expand before but failed for me as well, did some research and decided I'd rather place it on server:
[HttpGet]
public IQueryable<Challenge> ChallengesWithNotes()
{
return _contextProvider.Context.Challenges.Include("ChallengeNotes");
}
This should be parsed as expected. On client side you would query for "ChallengeNotes" instead of "Challenges" and you wouldn't need to write expand part.
I strongly suspect that the problem is due to your use of the [Queryable] attribute.
You must use the [BreezeQueryable] attribute instead!
See the documentation on limiting queries.
We are aware that Web API's QueryableAttribute has been deprecated in favor of EnableQueryAttribute in Web API v.1.5. Please stick with BreezeQueryable until we've had a chance to write a corresponding derived attribute for EnableQuery. Check with the documentation for the status of this development.

Is it possible to create an orchard autoroute using contents of a custom type property?

I have an Orchard cms module with some additional Content types set up and have added an AutoRoute component via code.
Everything works perfectly, however I am not happy with the default permalink pattern.
What I am trying to do is add a custom pattern and use one of the public properties in my content type. In my case the custom type has a public property called ClubName and I would like that to be used (It makes more sense from a routing perspective).
The Orchard part class name is called TrackPart.
I have tried {Content.TrackPart.ClubName}, {Content.Track.ClubName}, {ContentItem.TrackPart.ClubName},{Content.TrackPart.ClubName} and various other variations but nothing seems to be working.
I am really new to Orchard so there is a high chance I am missing something simple.
Any help would be greatly appreciated.
In response to feedback from #Bertrand-le-roy I created my own token by copying an example token. I can now get see the token in the drop down menu and select it. However the route pattern is still not working.
I can only assume that I have misunderstood the Evaluate() function's context.For usage. It looks like I am not getting the data I need
Here is what I have so far.
public class TrackPartTokens : ITokenProvider {
private readonly IContentManager _contentManager;
public TrackPartTokens(IContentManager contentManager) {
_contentManager = contentManager;
}
public Localizer T { get; set; }
public void Describe(dynamic context) {
context.For("Track", T("Track"), T("Tokens for Track"))
.Token("ClubName", T("ClubName"), T("The name of the club."))
;
}
public void Evaluate(dynamic context) {
context.For<TrackPart>("Track")
.Token("ClubName", (Func<TrackPart, object>)(field => field.ClubName))
.Chain("ClubName", "ClubName", (Func<TrackPart, object>)(field =>field.ClubName))
;
}</code>
The above code was based on the DateTimeField token inside the Orchard.Fields module.
context.For("DateTimeField")
.Token("Date", (Func)(field => field.DateTime))
.Chain("Date", "Date", (Func)(field => field.DateTime));
I had the same issue.
After some troubleshooting I managed to get the autoroute working by changing my implementaion to the following (adapted to your example, note that your setup might require some changes to the linq-function):
In your tokens-class:
First add a using System.Linq statement.
Then change your Evaluate implementation to the following:
context.For<IContent>("Content")
.Token("ClubName", (Func<IContent>, object>)(content =>
content.ContentItem.Parts.OfType<TrackPart>().First().ClubName));
Make sure your AutoroutePart settings in Migrations.cs uses the Content-prefix. Like:
.WithPart("AutoroutePart", partBuilder =>
partBuilder
.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions",
#"[{Name:'Track', Pattern:'{Content.ClubName}',
Description:'Your description'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
There seems to be some problems with the TokenManager-class in Orchard source that only allows the target-parameter to equal "Content" in order for the call: _data.TryGetValue(target, out value) to work (TokenManager.cs, line 67). I have tried a number of different setups but the _data-dictionary always only contain the "Content" key.
You'll have to make your own token. It's really easy. Copy a working example.

Resources