The Nlog has some ASP.NET logging features (see the list of layout renderers), for example
${aspnet-request}
For log form item, I need to know name of item.
${aspnet-request:form=myVariable}
But how to log all from items, which hames in unknown?
For example
${aspnet-request:form}
I'd write my own LayoutRenderer, myself (in fact, just did something nearly identical, recently) - one of the best parts about NLog is how extensible the framework is. Depending on how you're doing configuration will determine how you reference/load your custom layoutrenderer, but the sky is really the limit in terms of what you can do.
Off the top of my head, you could take one of two approaches with a custom renderer: wrap/extend the existing asp request renderer and just proxy all calls, or get a hook to the request object the same way the nlog one does (which is tricky; it calls out to grab the COM instance, if memory serves).
The approach I took was to embed the NameValueCollection in the outgoing LogEventInfo object itself (in the properties dictionary), then use a custom layout renderer to extract that collection and render it.
Related
So there are several parts to this question.
The 2 example endpoints (in simplest form):
user/{id}/profile
movie/{id}/info
I expect to create 2 controllers (UserController & MovieController).
How do I implement a view area before controller name?
Both of these are what I would consider a view. Therefore I would like to append a "view" in the url before the controller, as both controllers ONLY supply views. I later expect to also have a user controller in a different place that does NOT return views.
However, ALL my endpoints should start with /api/.
i.e. I want this:
api/view/user/{id}/profile
api/view/movie/{id}/info
But how do I register an area (/view/) while using "custom routing" (i.e.: httpConfiguration.MapHttpAttributeRoutes())? Any examples of this I couldn't find?
Where should I put versioning?
The client is an app, and will require versioning, so that we can make changes to the methods without breaking old versions of the app.
We are unsure where it would be best to place the versioning, and how the placement affects the development of new versions (if it does so at all?).
Possibilities:
1. api/v1/view/user/{id}/profile
2. api/view/v1/user/{id}/profile
3. api/view/user/{id}/profile/v1
version the whole API. This would upgrade the whole API to a new version, even if we only required a single method/endpoint to make an app-breaking change.
Are there any advantages to this that I am not seeing?
version the area. Same as above, just slightly fewer controllers affected.
version the method. Seems like the simplest, as only the single changed method is affected. But the url is very ugly.
Does anyone have an example of versioning in an MVC or Web Api structure that doesn't upgrade the whole API, but still keeps a somewhat nice structure in their URLs?
I ended up using https://github.com/Microsoft/aspnet-api-versioning as suggested by NightOwl888.
1.
Made my 2 controllers extend another controller with a const field that defined the routeprefix that they should share:
protected const string RoutePrefix = "api/view/v{version:apiVersion}";
...
[RoutePrefix(RoutePrefix + "/user")]
2.
The placement of the /v1/ doesn't matter with this Library. And allowed for either updating the controller or individuals methods, as seen fit per case basis.
I've to list, in specific folders or collections, objects expired also to anonymous users.
You know, portal_catalog returns only brains not expired. It's a useful behavior but not in this case...
To force the Catalog to return also expired contents, we've to pass a specific parameter: show_inactive.
Browsing the folder_listing (&family) code I noticed that it's possible to pass, via request, optionals parameters (contentFilter) to the query/getFolderContents. It's a nice feature to customize the query avoiding the creation of very similar listing templates.
I suppose it's necessary to create a marker interface to mark context (folders or collection) where I want to list also expired contents. For ex. IListExpired.
I imagine to ways:
1) to make a subscriber that intercepts before_traverse and , in the handler, a test to verify if the context implements the IListExpired. In positive case I made a
request.set('folderListing', {'show_inactive':True})
2) to make a viewlet for the IListExpired that in the call set
request.set('folderListing', {'show_inactive':True})
What's the best way? I suppose the first one could be an unnecessary overhead.
Vito
AFAIK, these are two separate thing: folderListing uses a method available to all CMF-based Folderish content types; show_inactive is an option of the Plone catalog, so you're not going to make it work as you're planning.
I think you should override these views and rewrite the listing using a catalog call.
you better use a browser layer for you package to do so or, a marker interface as you're planning.
I am building a site in which we are making moderate use of email templates. As in, HTML templates which we pass tokens into like {UserName}, {Email}, {NameFirst}, etc.
I am struggling with where to store these, as far as best practice goes. I'll first show the approach I took, and I'd be really excited to hear some expert perspective as a far as alternate approaches.
I created HTML templates in a folder called /Templates/.
I call a static method in my service layer, which takes in the following arguments:
UserName
UserID
Email
TemplatePath ("~/Templates")
Email Subject
Within the service layer I have my static method SendUserEmail() which makes use of a Template class - which takes a path, loads it as a string, and has a AddToken() Method.
Within my static SendUserEmail(), I build the token list off of the method signature, and send the email.
This makes for a quite long method call in my actual usage, especially since I am calling from the web.config the "TemplatePath", and "Email Subject". I could create a utility that has a shorter method call than the ConfigurationManager.AppSettings, but my concern is more that I don't usually see method signatures this long and I feel like it's because I'm doing something wrong.
This technique works great for the emails I have now, which at the most are using the first 3 tokens. However in the future I will have more tokens to pass in, and I'm just wondering what approach to take.
Do I create methods specific to the email needing to be sent? ie. SendNewUserRegistration(), SendMarketingMaterial(), and each has a different signature for the parameters?
I am using ASP.NET Membership, which contains probably the extend of all the fields I'll ever need. There are three main objects, aspnet_User, aspnet_Mebership and aspnet_profile. If it was all contained in one object, I would have just passed that in. Is there performance concerns with passing in all 3, to get all the fields I need? That is versus just passing in aspnet_User.UserID, aspnet_User.Email, etc?
I could see passing in a dictionary with the token entries, but I'm just wondering if that is too much to ask the calling page?
Is there a way to stick these in a config file of it's own called Templates.config, which has tags like -
<Templates>
<EmailTemplate Name="New User Registration">
<Tokens>
<UserName>
<UserID>
<Email>
</Tokens>
<Message Subject="Hi welcome...">
Hi {UserName}...
</Message>
</EmailTemplate>
</Templates>
I guess the main reason I'm asking, is because I'm having a hard time determining where the responsibility should be as far as determining what template to use, and how to pass in parameters. Is it OK if the calling page has to build the dictionary of TokenName, TokenValue? Or should the method take each in as a defined parameter? This looks out of place in the web.config, because I have 2 entries for and , and it feels like it should look more nested.
Thank you. Any techniques or suggestions of an objective approach I can use to ask whether my approach is OK.
First of all I would like to suggest you to use NVelocity as a template engine. As for main problem I think you can create an abstract class MailMessage and derive each one for every needed message (with unique template). So you will use this like following:
MailMessage message = new UserRegistrationMessage(tokens);
//some code that sends this message
Going this way you force each concrete XXXMessage class to be responsible for storing a template and filling it with the given tokens. How to deal with tokens? The simpliest way is to create a dictionary before passing it to the message, so each concrete message class will know how to deal with passed dictionary and what tokens it should contain, but you also need to remember what tokens it should contain. Another way (I like it more) is to create a general abstract type TokenSet and a derived one for every needed unique set of tokens. For example you can create a UserMessageTokenSet : TokenSet and several properties in it:
UserNameToken
SomeUserProfileDataToken
etc. So using this way you will always know, what data you should set for each token set and
UserRegistrationMessage will know what to take from this tokenSet.
There are a lot of ways to go. If you will describe you task better I think I will try suggest you something more concrete. But general idea is listed above. Hope it helps =)
How would you tackle this problem:
I have data in my data store. Each item has information about:
URL = an arbitrary number of first route segments that will be used with requests
some item type = display will be related to this type (read on)
title = used for example in navigation around my application
etc.
Since each item can have an arbitrary number of segments, I created a custom route, that allows me to handle these kind of requests without using the default route and having a single greedy route parameter.
Item type will actually define in what way should content of a particular item be displayed to the client. I was thinking of creating just as many controllers to not have too much code in a single controller action.
So how would you do this in ASP.NET MVC or what would you suggest would be the most feasible way of doing this?
Edit: A few more details
My items are stored in a database. Since they can have very different types (not inheritable) I thought of creating just as many controllers. But questions arise:
How should I create these controllers on each request since they are related to some dynamic data? I could create my own Controller factory or Route handler or possibly some other extension points as well, but which one would be best?
I want to use MVC basic functionality of using things like Html.ActionLink(action, controller, linkText) or make my own extension like Html.ActionLink(itemType, linkText) to make it even more flexible, so Action link should create correct routes based on Route data (because that's what's going on in the background - it goes through routes top down and see which one returns a resulting URL).
I was thinking of having a configuration of relation between itemType and route values (controller, action, defaults). Defaults setting may be tricky since defaults should be deserialized from a configuration string into an object (that may as well be complex). So I thought of maybe even having a configurable relation between itemType and class type that implements a certain interface like written in the example below.
My routes can be changed (or some new ones added) in the data store. But new types should not be added. Configuration would provide these scenarios, because they would link types with route defaults.
Example:
Interface definition:
public interface IRouteDefaults
{
object GetRouteDefaults();
}
Interface implementation example:
public class DefaultType : IRouteDefaults
{
public object GetRouteDefaults()
{
return new {
controller = "Default",
action = "Show",
itemComplex = new Person {
Name = "John Doe",
IsAdmin = true
}
}
}
Configuration example:
<customRoutes>
<route name="Cars" type="TypeEnum.Car" defaults="MyApp.Routing.Defaults.Car, MyApp.Routing" />
<route name="Fruits" type="TypeEnum.Fruit" defaults="MyApp.Routing.Defaults.Fruit, MyApp.Routing" />
<route name="Shoes" type="TypeEnum.Shoe" defaults="MyApp.Routing.Defaults.Shoe, MyApp.Routing" />
...
<route name="Others" type="TypeEnum.Other" defaults="MyApp.Routing.Defaults.DefaultType, MyApp.Routing" />
</customRoutes>
To address performance hit I can cache my items and work with in-memory data and avoid accessing the database on each request. These items tend to not change too often. I could cache them for like 60 minutes without degrading application experience.
There is no significant performance issue if you define a complex routing dictionary, or just have one generic routing entry and handle all the cases yourself. Code is code
Even if your data types are not inheritable, most likely you have common display patterns. e.g.
List of titles and summary text
item display, with title, image, description
etc
If you can breakdown your site into a finite number of display patterns, then you only need to make those finite controllers and views
You them provide a services layer which is selected by the routing parameter than uses a data transfer object (DTO) pattern to take the case data and move it into the standard data structure for the view
The general concept you mention is not at all uncommon and there are a few things to consider:
The moment I hear about URL routing taking a dependency on data coming from a database, the first thing I think about is performance. One way to alleviate potentialy performance concerns is to use the built in Route class and have a very generic pattern, such as "somethingStatic/{*everythingElse}". This way if the URL doesn't start with "somethingStatic" it will immediately fail to match and routing will continue to the next route. Then you'll get all the interesting data as the catch-all "everythingElse" parameter.
You can then associate this route with a custom route handler that derives from MvcRouteHandler and overrides GetHttpHandler to go to the database, make sense of the "everythingElse" value, and perhaps dynamically determine which controller and action should be used to handle this request. You can get/set the routing values by accessing requestContext.RouteData.Values.
Whether to use one controller and one action or many of one or many of each is a discussion unto itself. The question boils down to how many different types of data do you have? Are they mostly similar (they're all books, but some are hardcover and some are softcover)? Completely different (some are cars, some are books, and some are houses)? The answer to this should be the same answer you'd have if this were a computer programming class and you had to decide from an OOP perspective whether they all have a base class and their own derives types, or whether they could be easily represented by one common type. If they're all different types then I'd recommend different controllers - especially if each requires a distinct set of actions. For example, for a house you might want to see an inspection report. But for a book you might want to preview the first five pages and read a book review. These items have nothing in common: The actions for one would never be used for the other.
The problem described in #3 can also occur in reverse, though: What if you have 1,000 different object types? Do you want 1,000 different controllers? Without having any more information, I'd say for this scenario 1,000 controllers is a bit too much.
Hopefully these thoughts help guide you to the right solution. If you can provide more information about some of the specific scenarios you have (such as what kind of objects these are and what actions can apply to them) then the answer can be refined as well.
I wonder whether there is a workaround for using the standard XmlSiteMapProvider within a non asp.net application, like WinForm/Console or, in my case, VS Unit Test one.
The following code fails, because it cannot create a path to the .sitemap file inside a private GetConfigDocument method.
XmlSiteMapProvider provider = new XmlSiteMapProvider();
NameValueCollection providerAttributes = new NameValueCollection();
providerAttributes.Add("siteMapFile", "Web.sitemap");
provider.Initialize("XmlSiteMapReader", providerAttributes);
provider.BuildSiteMap();
I feel the right solution is to write another provider.
I do not see why not. It is just a provider that implements an interface. You may not need many of the features, but you can access the API for what it provides you. Your WinForms screens can simply use the Urls for identification so that you can determine your place in the hierarchy.
What you may have to do is create a custom implementation of the provider because it will use the HttpContext to get the Url of the current web request to identify current placement while you will need to get that value differently. That is what could be tricky because your WinForm application could be displaying multiple windows at time. If you know there is only one window showing at a time you could use a static value which is set prior to accessing the SiteMap API.
Now you have to question the value of using an API if you have to do all of the work. There may not be enough benefit to make it worthwhile.