Use TagBuilder in webform project? - asp.net

I have a old webform project that I have now set to .net 4.0. I have added the System.Web.MVC ref 4.0 but the TabBuilder do still not show up as a known type?
Edit : I have also tried adding System.Web.WebPages 2.0 but that do not solve the problem.

Please test this code and see this maybe you forget using
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcApplication1.Helpers
{
public static class ImageHelper
{
public static string Image(this HtmlHelper helper, string id, string url, string alternateText)
{
return Image(helper, id, url, alternateText, null);
}
public static string Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)
{
// Create tag builder
var builder = new TagBuilder("img");
// Create valid id
builder.GenerateId(id);
// Add attributes
builder.MergeAttribute("src", url);
builder.MergeAttribute("alt", alternateText);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
// Render tag
return builder.ToString(TagRenderMode.SelfClosing);
}
}
}

Related

What is the default parameter type in .net core web api?

For example, I have an API like this:
[HttpPost("device")]
public string Post(string uid, string name)
{
return "value";
}
Will this code I posted work? By default?
form-data or x-www-form-urlencoded or raw?
I know If I want to post json data I have to add the [FromBody] and the parameter into a class right?
Question 2: how to post json data to the API, but do not have to use a instance of the parameter but can use the parameter?
string uid, string deviceId
Q1: I newly created an asp.net core 3.1 api project and create a new HomeController, and it worked in my side
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
[HttpPost("device")]
public string Post(string uid, string name)
{
return "value";
}
}
}
Q2: I think there might be some way to realize your goal but I'm afraid that needs more configuration such as adding a middleware. So I'm afraid the easiest way to receive json data is using an entity which contains the parameters. And if you consists on not creating entity for that data format, maybe you can use Dictionary like code below:
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
[HttpPost("device")]
public string Post([FromBody] Dictionary<string, string> test)
{
string uid = test.GetValueOrDefault("uid");
string name = test.GetValueOrDefault("name");
return "value";
}
}
}

How to make ASP.NET to stop interpret null as string

I have a Web API method:
public List<Task> GetTasks([FromUri] TaskFilter filter)
{
}
The method has parameter with list of nullable identifiers:
public class TaskFilter
{
public IList<int?> Assignees { get; set; }
}
When I call it:
GET /tasks?assignees=null
Server returns an error:
{
"message":"The request is invalid.",
"modelState": {
"assignees": [ "The value 'null' is not valid for Nullable`1." ]
}
}
It works only if I pass empty string:
GET /tasks?assignees=
But standard query string converters (from JQuery, Angular, etc) do not work with nulls in such way.
How to make ASP.NET to interpret 'null' as null?
Upd: The query string can contain several identifiers, e.g.:
GET /tasks?assignees=1&assignees=2&assignees=null
Upd2: JQuery converts nulls in array to empty strings, and ASP.NET interprets them as null. So the question is about calling WebAPI from Angular 1.6 ($HttpParamSerializerProvider)
Upd3: I know about workarounds, but I do not ask for them. I want a solution for specific problem:
It is a GET method
Method accepts a list from Uri
A list can contain null values
It should be List<int?> because API docs are generated automatically, and I do not want to see text array as parameter type
By default ASP.NET expects empty strings for null values (JQuery.param works in that way)
But some client libraries (e.g. Angular) does not convert null array items to empty strings
You can create a custom model bind for this specific type, inherithing from DefaultModelBinder, for sample:
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
public class TaskFilterBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
var assignees = request.QueryString["assignees"];
if (assignees == "null") // check if assignees is null (string) then return NULL
return null;
return assignees;
}
}
Finally we need to inform the controller as to the binding we want it to use. This we can specify using attributes
[ModelBinder(typeof(TaskFilterBinder))]
as below:
public List<Task> GetTasks([FromUri(ModelBinder=typeof(TaskFilterBinder))] TaskFilter filter)
{
// Do your stuff.
}
For more reference check this link on Custom Model Binders.
Hope, this solves your problem . Thanks
Finally, I found a solution using custom value provider:
using System;
using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.ValueProviders;
using System.Web.Http.ValueProviders.Providers;
using System.Globalization;
using System.Net.Http;
using System.Web.Http.ModelBinding;
public sealed class NullableValueProviderAttribute : ModelBinderAttribute
{
private readonly string[] _nullableColumns;
public NullableValueProviderAttribute(params string[] nullableColumns)
{
_nullableColumns = nullableColumns;
}
public override IEnumerable<ValueProviderFactory> GetValueProviderFactories(HttpConfiguration configuration)
{
return new ValueProviderFactory[] { new NullableValueProviderFactory(_nullableColumns) };
}
}
public class NullableValueProviderFactory : ValueProviderFactory, IUriValueProviderFactory
{
private readonly string[] _nullableColumns;
public NullableValueProviderFactory(string[] nullableColumns)
{
_nullableColumns = nullableColumns;
}
public override IValueProvider GetValueProvider(HttpActionContext actionContext)
{
return new NullableQueryStringValueProvider(actionContext, CultureInfo.InvariantCulture, _nullableColumns);
}
}
public class NullableQueryStringValueProvider : NameValuePairsValueProvider
{
private static readonly string[] _nullValues = new string[] { "null", "undefined" };
private static IEnumerable<KeyValuePair<string, string>> GetQueryNameValuePairs(HttpRequestMessage request, string[] nullableColumns)
{
foreach (var pair in request.GetQueryNameValuePairs())
{
var isNull = Array.IndexOf(nullableColumns, pair.Key) >= 0 && Array.IndexOf(_nullValues, pair.Value) >= 0;
yield return isNull ? new KeyValuePair<string, string>(pair.Key, "") : pair;
};
}
public NullableQueryStringValueProvider(HttpActionContext actionContext, CultureInfo culture, string[] nullableColumns) :
base(GetQueryNameValuePairs(actionContext.ControllerContext.Request, nullableColumns), culture)
{ }
}
And specify it in Web API action:
public List<Task> GetTasks([NullableValueProvider("assignees")] TaskFilter filter)
{
}

How can I customise how Razor converts values of certain types to text?

Imagine I have some custom type:
public class CustomType
{
public override string ToString() {
return "Default";
}
}
Next, imagine I use an instance of this type in a Razor view:
#model CustomType
<span>The custom type is #Model</span>
Razor seems to use ToString to convert the value into text for the resulting HTML. However, I want to tell Razor that whenever it wants to format a CustomType, it should use some given custom formatting logic.
Is this possible? If so, how can I do it?
You could do it with an HtmlHelper
#Html.CustomFormattingLogic(Model)
public static class MyHtmlHelperExtensions
{
public static MvcHtmlString CustomFormattingLogic(this HtmlHelper htmlHelper,
CustomType model)
{
var customString = MethodToDoFormatting(model);
return MvcHtmlString.Create(customString);
}
}
...as another option, you could have an extension method do custom formatting:
public static class MyCustomTypeExtensions
{
public static string CustomFormattingLogic(this CustomType model)
{
var customString = MethodToDoFormatting(model);
return customString;
}
}

How to call Ajax.BeginForm from a custom helper method?

Can I call Ajax.BeginFrom from a custom helper method ?
AjaxHelper is not available in a custom helper method, so I tried to pass the "Ajax" available in ViewPage to Helper method while calling it, but then in method, BeginForm is not available on that passed "Ajax" parameter.
You could instantiate it:
public static class HtmlExtensions
{
public static MvcHtmlString Foo(this HtmlHelper htmlHelper)
{
var ajaxHelper = new AjaxHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
var form = ajaxHelper.BeginForm();
// ... use the ajaxHelper and htmlHelper
}
}
or if you are writing an extension method on AjaxHelper:
public static class AjaxExtensions
{
public static MvcHtmlString Foo(this AjaxHelper AjaxHelper)
{
var htmlHelper = new HtmlHelper(AjaxHelper.ViewContext, AjaxHelper.ViewDataContainer);
// ... use the ajaxHelper and htmlHelper
}
}
And don't forget the proper usings if you want to bring other extension methods into scope:
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Mvc.Ajax;

Serialising and deserialising a JSON object returned by an ASP.Net web service

I have a simple ASP.Net web service / script method that returns a JSON object which is then modified and send back to the page during post back - I need to be able to deserialise this object:
public class MyWebPage : Page
{
[WebMethod]
[ScriptMethod]
public static MyClass MyWebMethod()
{
// Example implementation of my web method
return new MyClass()
{
MyString = "Hello World",
MyInt = 42,
};
}
protected void myButton_OnClick(object sender, EventArgs e)
{
// I need to replace this with some real code
MyClass obj = JSONDeserialise(this.myHiddenField.Value);
}
}
// Note that MyClass is contained within a different assembly
[Serializable]
public class MyClass : IXmlSerializable, ISerializable
{
public string MyString { get; set; }
public int MyInt { get; set; }
// IXmlSerializable and ISerializable implementations not shown
}
I can make changes to both the web method MyWebMethod, and also to a certain extent MyClass, however MyClass needs to implemnt both IXmlSerializable and ISerializable, and is contained within a separate assembly - I mention this because these have caused problems for me so far.
How can I do this? (either using standard .Net types or using something like JSON.Net)
You can use JavaScriptSerializer class from System.Web.Extensions to deserialize JSON string. For example, the following code converts hash into .NET dictionary object:
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string,int>>("{ a: 1, b: 2 }");
Console.WriteLine(dict["a"]);
Console.WriteLine(dict["b"]);
Console.ReadLine();
}
}
}
Code output is:
1
2
JavaScriptSerializer is the class that static page methods use to serialize their responses, so it's also what's appropriate for deserializing that particular JSON:
protected void myButton_OnClick(object sender, EventArgs e)
{
string json = myHiddleField.Value;
MyClass obj = new JavaScriptSerializer().Deserialize<MyClass>(json);
}

Resources