ASP.net how to extend a control or collection - asp.net

I am attempting to extend a List. When using Visual Studio there are the different code hints for all the functions I can use with a List object. How can I extend the functionality of the List to show my new function?
public class ListExtensionHelper<T> : System.Collections.Generic.List<T>
{
public List<T> AwesomeFunction<T>()
{
}
}
For the life of me I could not find anything online on how I would do it for a List

If you are trying to add AwesomeFunction as an extension method to a regular List object, then you need to define an extension method in a static class:
public static class ListExtensions
{
public static List<T> AwesomeFunction<T>(this List<T> list)
{
}
}
Otherwise, the code you have should work; if you instantiate the ListExtensionHelper class, it should have all the functions of List as well as AwesomeFunction.

It sounds like you're looking for extension methods, rather than inheritance.
There are some really good examples here. There's also a really good library of extensions available here.
<soapbox>
One of my personal favorites that I use is this:
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string s)
{
return string.IsNullOrEmpty(s);
}
}
It's ridiculously simple, but a huge pet peeve of mine is having to write:
if (string.IsNullOrEmpty(someVariable))
as opposed to:
if (someVariable.IsNullOrEmpty())
For me it's just a matter of being a natural construct of my native language. The built-in method sounds like:
object verb subject
whereas mine sounds like:
subject verb
It's probably silly, but when I want to act upon a subject it just makes more sense for me to start with the subject :)
</soapbox>

Related

Binding method names declaratively?

Finding the need to be able to get method names in a declarative manner (for AOP, reflection, etc) such that compiler checking enforces breaking changes etc. Good example:
invocation.Method.Name.Equals("GetAll"
.. is there a way to do this like with a lambda/generic method so i don't have to put the method name as a string literal?
I've used things like this before to get property names:
public static string GetPropertyName<T, P>(Expression<Func<T, P>> propSelector)
where T : class
{
return (propSelector.Body as MemberExpression).Member.Name;
}
.. but is there a reliable and easy way to do the same for methods?
You can do something like this with delegates:
public static string MethodName(Delegate d) {
return d.Method.Name;
}
// and to use...
MethodName(new Func<object, int>(Convert.ToInt32));
If there's a particular delegate signature you use, you can create specific overloads:
public static string MethodName(Func<object, int> d) {
return MethodName((Delegate)d);
}
MethodName(Convert.ToInt32);
You might also be able to do something with generics, if you have a play around with it.

ASP MVC dynamic fields in editor

I have a form which will include some optional questions that need to asked of the user. In my model it may look like:
public Dictionary<String, String> Questions { get; set; }
Where the key is the label and value is the text box. How can I create and populate the controls for this? I am new to ASP MVC, but it makes sense that something like this would be built in.
Is there a built in way to do this, or do I have to implement it myself? It seems like there should be a helper for it, since you don't really want to put this kind of code in the view.
I've tried
Html.EditorFor(model => model.Questions);
But it just spits out "[key, value]" to the view.
There are a couple of ways you could go here.
You could write your own helper quite easily - maybe something like this:
public static string Question(Dictionary question)
{
Html.Label(question.Key);
Html.Textbox(question.Value);
}
Create a custom display template for Dictionary<string, string> (or, rather, wrap the dictionary in a Question type to avoid ambiguity) that outputs what you want.
Why not implement a Question class?
Something like this I had in mind:
public class QuestionControl
{
public int QuestionId{get;set;}
public string Question{get;set;}
public string Answer{get;set;}
public virtual string GetHtml()
{
return string.Format("<label for=\"{0}\">{2}</label><br><input type=\"text\" name=\"{0}\" id=\"{0}\" value=\"{1}\">", QuestionId, Answer, Question);
}
}
Also, this way you can inherit and override GetHtml and have questions with checkboxes, radiobuttons etc.

Can I create a column of nvarchar(MAX) using FluentMigrator?

Using FluentMigrator, the default creation of a Column using .AsString() results in an nvarchar(255). Is there a simple way (before I modify the FluentMigrator code) to create a column of type nvarchar(MAX)?
You could create an extension method to wrap .AsString(Int32.MaxValue) within .AsMaxString()
e.g.
internal static class MigratorExtensions
{
public static ICreateTableColumnOptionOrWithColumnSyntax AsMaxString(this ICreateTableColumnAsTypeSyntax createTableColumnAsTypeSyntax)
{
return createTableColumnAsTypeSyntax.AsString(int.MaxValue);
}
}
OK, I found it. Basically, use .AsString(Int32.MaxValue). Pity there's not a .AsMaxString() method, but I guess it's easy enough to put in...
You can use AsCustom("nvarchar(max)") and pack it to extension
If you often create columns/tables with the same settings or groups of columns, you should be creating extension methods for your migrations!
For example, nearly every one of my tables has CreatedAt and UpdatedAt DateTime columns, so I whipped up a little extension method so I can say:
Create.Table("Foos").
WithColumn("a").
WithTimestamps();
I think I created the Extension method properly ... I know it works, but FluentMigrator has a LOT of interfaces ... here it is:
public static class MigrationExtensions {
public static ICreateTableWithColumnSyntax WithTimestamps(this ICreateTableWithColumnSyntax root) {
return root.
WithColumn("CreatedAt").AsDateTime().NotNullable().
WithColumn("UpdatedAt").AsDateTime().NotNullable();
}
}
Similarly, nearly every one of my tables has an int primary key called 'Id', so I think I'm going to add Table.CreateWithId("Foos") to always add that Id for me. Not sure ... I actually just started using FluentMigrator today, but you should always be refactoring when possible!
NOTE: If you do make helper/extension methods for your migrations, you should never ever ever change what those methods do. If you do, someone could try running your migrations and things could explode because the helper methods you used to create Migration #1 works differently now than they did earlier.
Here is the code for creating columns incase it helps you create helper methods: https://github.com/schambers/fluentmigrator/blob/master/src/FluentMigrator/Builders/Create/Column/CreateColumnExpressionBuilder.cs
How about extending like this:
public static class StringMaxMigratorExtensions
{
public static ICreateTableColumnOptionOrWithColumnSyntax AsStringMax(this ICreateTableColumnAsTypeSyntax createTableColumnAsTypeSyntax)
{
return createTableColumnAsTypeSyntax.AsCustom("nvarchar(max)");
}
public static IAlterColumnOptionSyntax AsStringMax(this IAlterColumnAsTypeSyntax alterColumnAsTypeSyntax)
{
return alterColumnAsTypeSyntax.AsCustom("nvarchar(max)");
}
}

strongly typed sessions in asp.net

Pardon me if this question has already been asked. HttpContext.Current.Session["key"] returns an object and we would have to cast it to that particular Type before we could use it. I was looking at various implementations of typed sessions
http://www.codeproject.com/KB/aspnet/typedsessionstate.aspx
http://weblogs.asp.net/cstewart/archive/2008/01/09/strongly-typed-session-in-asp-net.aspx
http://geekswithblogs.net/dlussier/archive/2007/12/24/117961.aspx
and I felt that we needed to add some more code (correct me if I was wrong) to the SessionManager if we wanted to add a new Type of object into session, either as a method or as a separate wrapper. I thought we could use generics
public static class SessionManager<T> where T:class
{
public void SetSession(string key,object objToStore)
{
HttpContext.Current.Session[key] = objToStore;
}
public T GetSession(string key)
{
return HttpContext.Current.Session[key] as T;
}
}
Is there any inherent advantage in
using
SessionManager<ClassType>.GetSession("sessionString")
than using
HttpContext.Current.Session["sessionString"] as ClassType
I was also thinking it would be nice
to have something like
SessionManager["sessionString"] = objToStoreInSession,
but found that a static class cannot have an indexer. Is there any other way to achieve this ?
My thought was create a SessionObject which would store the Type and the object, then add this object to Session (using a SessionManager), with the key. When retrieving, cast all objects to SessionObject ,get the type (say t) and the Object (say obj) and cast obj as t and return it.
public class SessionObject { public Type type {get;set;} public Object obj{get;set;} }
this would not work as well (as the return signature would be the same, but the return types will be different).
Is there any other elegant way of saving/retrieving objects in session in a more type safe way
For a very clean, maintainable, and slick way of dealing with Session, look at this post. You'll be surprised how simple it can be.
A downside of the technique is that consuming code needs to be aware of what keys to use for storage and retrieval. This can be error prone, as the key needs to be exactly correct, or else you risk storing in the wrong place, or getting a null value back.
I actually use the strong-typed variation, since I know what I need to have in the session, and can thus set up the wrapping class to suit. I've rather have the extra code in the session class, and not have to worry about the key strings anywhere else.
You can simply use a singleton pattern for your session object. That way you can model your entire session from a single composite structure object. This post refers to what I'm talking about and discusses the Session object as a weakly typed object: http://allthingscs.blogspot.com/2011/03/documenting-software-architectural.html
Actually, if you were looking to type objects, place the type at the method level like:
public T GetValue<T>(string sessionKey)
{
}
Class level is more if you have the same object in session, but session can expand to multiple types. I don't know that I would worry about controlling the session; I would just let it do what it's done for a while, and simply provide a means to extract and save information in a more strongly-typed fashion (at least to the consumer).
Yes, indexes wouldn't work; you could create it as an instance instead, and make it static by:
public class SessionManager
{
private static SessionManager _instance = null;
public static SessionManager Create()
{
if (_instance != null)
return _instance;
//Should use a lock when creating the instance
//create object for _instance
return _instance;
}
public object this[string key] { get { .. } }
}
And so this is the static factory implementation, but it also maintains a single point of contact via a static reference to the session manager class internally. Each method in sessionmanager could wrap the existing ASP.NET session, or use your own internal storage.
I posted a solution on the StackOverflow question is it a good idea to create an enum for the key names of session values?
I think it is really slick and contains very little code to make it happen. It needs .NET 4.5 to be the slickest, but is still possible with older versions.
It allows:
int myInt = SessionVars.MyInt;
SessionVars.MyInt = 3;
to work exactly like:
int myInt = (int)Session["MyInt"];
Session["MyInt"] = 3;

What is the best way to reuse functions in Flex MVC environment?

I am using a Cairngorm MVC architecture for my current project.
I have several commands which use the same type of function that returns a value. I would like to have this function in one place, and reuse it, rather than duplicate the code in each command. What is the best way to do this?
Create a static class or static method in one of your Cairngorm classes.
class MyStatic
{
public static function myFunction(value:String):String
{
return "Returning " + value;
}
}
Then where you want to use your function:
import MyStatic;
var str:String = MyStatic.myFunction("test");
Another option is to create a top level function (a la "trace"). Check out this post I wrote here.
You have lots of options here -- publicly defined functions in your model or controller, such as:
var mySharedFunction:Function = function():void
{
trace("foo");
}
... static methods on new or existing classes, etc. Best practice probably depends on what the function needs to do, though. Can you elaborate?
Create an abstract base class for your commands and add your function in the protected scope. If you need to reuse it anywhere else, refactor it into a public static method on a utility class.

Resources