My requirement is to create a web api in c# that will create another API According to the document.
User will send api name, action method name , Request and type of operation that need to be performed by the new api and our api will create the required api and return response that contain API url and request/response type.
I have searched in lot of different website but i did't found anything related to it. if anyone have solution of it or any close idea please share. i need to do this in asp.net MVC
I have a sample program that uses CodeDomCompiler that generates a standard Telemetry implementation for any given interface. The code is compiled to memory and loaded into the address space. This sounds like what you are trying to do. If so, take stab at generating some code using the samples and ask questions as you encounter problems.
This may help you get started.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using TelemeterFactory;
namespace ConsoleTelemeter
{
/// <summary>Generate a CSharp Telemeter that calls Console.WriteLine as its output.</summary>
public class Factory : FactoryBase
{
public override string[] GenerateSource(SourceGenerationOptions options)
{
var generatedClassName = options.Type.Name + "_" + options.FactoryOptions.ClassName;
var text = this.CSharpTemplate()
.Replace("<codeGenerationTool>", $"{nameof(ConsoleTelemeter)} {Assembly.GetExecutingAssembly().GetName().Version} {DateTimeOffset.UtcNow:yyyy-MM-dd HH:mm:ss zzz}")
.Replace("<generatedNamespace>", options.FactoryOptions.Namespace)
.Replace("<generatedClassName>", generatedClassName)
.Replace("<interfaceImplemented>", options.Type.FullName)
.Replace("//<privateFields>", "private const string Null = \"<null>\";")
.Replace("//<publicMethodImplementations>", Methods(options.Methods))
.Replace("\t", " ")
;
return new[] { text, $"{options.FactoryOptions.Namespace}.{generatedClassName}" };
}
private string Methods(IReadOnlyList<MethodInfo> methods)
{
var sb = new StringBuilder(4096);
foreach (var method in methods)
{
// method start
sb.AppendFormat("\n\t\tpublic {0} {1} (", method.ReturnType, method.Name);
var comma = string.Empty;
foreach (ParameterInfo parameter in method.GetParameters())
{
sb.AppendFormat("{0}{1} {2}", comma, parameter.ParameterType, parameter.Name);
comma = ", ";
}
sb.Append(") {\n");
sb.Append("\t\t\tvar result = $\"{DateTimeOffset.UtcNow:yyyy-MM-dd HH:mm:ss.ffffff} ");
sb.Append("{nameof(");
sb.Append(method.Name);
sb.Append(")}: ");
comma = string.Empty;
foreach (ParameterInfo parameter in method.GetParameters())
{
var t = parameter.ParameterType;
sb.AppendFormat("{0}{{nameof({1})}}={{", comma, parameter.Name);
// special case for boolean parameters to be coerced to strings below. Not strictly necessary for this Telemeter but show how one could do it if necessary.
sb.AppendFormat("{1}{0}", parameter.Name, t == typeof(Boolean) ? "(" : string.Empty);
if (t == typeof(string))
{
sb.Append(" ?? Null");
}
else if (t == typeof(Int32)
|| t == typeof(float)
|| t == typeof(double)
|| t == typeof(Int64)
|| t == typeof(decimal)
|| t == typeof(Int16))
{
sb.Append(":#0");
}
else if (t.BaseType == typeof(Enum))
{
sb.Append(":D");
}
else if (t == typeof(Boolean))
{
sb.Append("? \"1\" : \"0\")");
}
else
{
sb.Append(".ToString() ?? Null");
}
sb.Append("}");
comma = ",";
}
sb.Append("\";\n\t\t\treturn result;\n");
// method end
sb.Append("\t\t}\n");
}
return sb.ToString();
}
}
}
Related
I want to ask you regarding for the searching in C# and why there is a Not Found statement if already found the answer or the data itself.
Here is the code:
Console.WriteLine("Enter Plate Number: ");
string plateNumber1 = Console.ReadLine();
var searchPlateNumberDAL = new ParkingSystemDAL(_iconfiguration);
var listSlotParking = searchPlateNumberDAL.GetList();
listSlotParking.ForEach(item =>
{
bool searchItem = item.plateNumber == plateNumber1;
if (searchItem == true)
{
Console.WriteLine(item.parkingId);
}
else
{
Console.WriteLine("Not Found");
}
});
output
I think there some garbage value is present.
So, code will be
if(item.plateNumber.ToString().Trim().ToUpper() == plateNumber1.ToString().Trim().ToUpper())
{
Console.WriteLine(item.parkingId);
}
you can also use Linq Where expression instead of ForEach
if( listSlotParking.Where(x =>x.planteNumberplateNumber.ToString().Trim().ToUpper() == plateNumber1.ToString().Trim().ToUpper()).ToList().Count()>0)
{
Console.WriteLine(item.parkingId);
}
Try
item.plateNumber.Trim() == plateNumber1.Trim()
I've successfully implemented this Helper 1 and it works fine out of the box. My issue is i'm trying to extend it to allow Search of List.
Example.
Class Journalist
public string Name { get; set; }
public List<Publication> Publications { get; set; }
In my DataTables columns
{
"width": "25%", "target": 3, "data" : "Publications",
"render": function (data, type, full, meta) {
return PublicationLoop(data);
}
}
function PublicationLoop(data) {
var content = '';
$.each(data, function(propName, propVal) {
content += '' + propVal.Name + ', ';
});
return content.substr(0, content.length - 2);;
}
The above all works fine but the Helper does not find the content in the Publications Column because it doesn't recognize the type but I can;t figure out how to amend the Helper to Search in the Name field of List.
public static IQueryable<T> ToGlobalSearchInAllColumn<T>(this IQueryable<T> table, DTParameters Param)
{
var GlobalSearchText = Param.Search != null && Param.Search.Value != null ? Param.Search.Value : string.Empty;
if (!string.IsNullOrEmpty(GlobalSearchText))
{
// return BooksData.Where(x => x.BookId.ToString() == GlobalSearchText || x.BookName.Contains(GlobalSearchText) || x.Category.Contains(GlobalSearchText));
StringBuilder WhereQueryMaker = new StringBuilder();
Type SearchType = table.FirstOrDefault().GetType();
DateTime CreatedOn;
foreach (PropertyInfo prop in SearchType.GetProperties())
{
if (prop.PropertyType == typeof(System.String))
WhereQueryMaker.Append((WhereQueryMaker.Length == 0 ? "" : " OR ") + prop.Name + ".Contains(#0)");
// -> This is the line I'm try to add but the Query causes the app to fail.
else if (prop.PropertyType == typeof(List<Business.Publication>))
WhereQueryMaker.Append((WhereQueryMaker.Length == 0 ? "" : " OR ") + prop.Name + ".Contains(#0)");
else if (prop.PropertyType == typeof(System.Int32))
//if data type is integer then you need to parse to ToString() to use Contains() function
WhereQueryMaker.Append((WhereQueryMaker.Length == 0 ? "" : " OR ") + prop.Name + ".ToString().Contains(#0)");
else if (prop.PropertyType == typeof(System.DateTime?) && DateTime.TryParseExact(GlobalSearchText, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out CreatedOn))
//Date object comparison required to follow DateTime(2018,08,15) as format. so need to supply yyyy, MM, dd value on it.
WhereQueryMaker.Append((WhereQueryMaker.Length == 0 ? "" : " OR ") + prop.Name + "== DateTime(" + CreatedOn.Year + ", " + CreatedOn.Month + ", " + CreatedOn.Day + ")");
}
return table.Where(WhereQueryMaker.ToString(), GlobalSearchText);
}
return table;
}
The error it throws
'No generic method 'Contains' on type 'System.Linq.Enumerable' is
compatible with the supplied type arguments and arguments. No type
arguments should be provided if the method is non-generic. '
Put a watches on SearchType.GetProperties() and prop. Then put a breakpoint while looping and look to see what types are present. Then set your else if check for whatever it needs to be for the Publications column.
I have web api application and I want to sanitize data that comes from front-end applications using web api filters.
I have created the following filter:
public class StringFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
foreach (var actionArgument in actionContext.ActionArguments)
{
if (actionArgument.Value.GetType() == typeof(string))
{
var sanitizedString = actionArgument.Value.ToString().Trim();
sanitizedString = Regex.Replace(sanitizedString, #"\s+", " ");
actionContext.ActionArguments[actionArgument.Key] = sanitizedString;
}
else
{
var properties = actionArgument.Value.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(x => x.CanRead && x.PropertyType == typeof(string) && x.GetGetMethod(true).IsPublic && x.GetSetMethod(true).IsPublic);
foreach (var propertyInfo in properties)
{
var sanitizedString = propertyInfo.GetValue(actionArgument.Value).ToString().Trim();
sanitizedString = Regex.Replace(sanitizedString, #"\s+", " ");
propertyInfo.SetValue(actionArgument.Value, sanitizedString);
}
}
}
}
}
The problem with this code is the code inside if statement where I want to sanitize the arguments passed as single string I got this error:
"ClassName": "System.InvalidOperationException",
"Message": "Collection was modified; enumeration operation may not execute.
But if my web api action takes a parameter as dto object which has string properties the code(which is inside the else statement) is working perfectly and strings are sanitized before starting executing the action.
So my question how to sanitize the passed argument in case it was string parameter?
You are trying to modify the same collection while enumerating it, which is not allowed. Call .ToList() so that you are enumerating a separate collection while modifying the original. ie foreach (var actionArgument in actionContext.ActionArguments.ToList()) {...
public override void OnActionExecuting(HttpActionContext actionContext) {
foreach (var actionArgument in actionContext.ActionArguments.ToList()) {
if (actionArgument.Value != null && actionArgument.Value is string) {
var sanitizedString = actionArgument.Value.ToString().Trim();
sanitizedString = Regex.Replace(sanitizedString, #"\s+", " ");
actionContext.ActionArguments[actionArgument.Key] = sanitizedString;
} else {
var properties = actionArgument.Value.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(x => x.CanRead && x.PropertyType == typeof(string) && x.GetGetMethod(true).IsPublic && x.GetSetMethod(true).IsPublic);
foreach (var propertyInfo in properties) {
var sanitizedString = propertyInfo.GetValue(actionArgument.Value).ToString().Trim();
sanitizedString = Regex.Replace(sanitizedString, #"\s+", " ");
propertyInfo.SetValue(actionArgument.Value, sanitizedString);
}
}
}
}
I am developing one application in web api and angularjs. I have file upload part. I am able to upload files and i am not storing files in webroot(i created folder called Uploads). My problem is i am not using any good naming convention to maintain uniqueness of files so there are chances of overriding files. I am new to angularjs so i refered below link. http://instinctcoder.com/angularjs-upload-multiple-files-to-asp-net-web-api/
This is my controller level code.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var uploadPath = HttpContext.Current.Server.MapPath("~/Uploads");
var multipartFormDataStreamProvider = new CustomUploadMultipartFormProvider(uploadPath);
await Request.Content.ReadAsMultipartAsync(multipartFormDataStreamProvider);
var fileName = "";
DateTime dt = DateTime.Now;
foreach (var key in multipartFormDataStreamProvider.Contents)
{
var a = key.Headers;
fileName = a.ContentDisposition.FileName;
break;
}
foreach (var key in multipartFormDataStreamProvider.FormData.AllKeys)
{
foreach (var val in multipartFormDataStreamProvider.FormData.GetValues(key))
{
Console.WriteLine(string.Format("{0}: {1}", key, val));
}
}
In the above code I am trying to add date part to beginning of file name as below
string filenameNew = "App1" + DateTime.Now.ToString("yyyyMMddHHmmss");
fileName = filenameNew + a.ContentDisposition.FileName;
public CustomUploadMultipartFormProvider(string path) : base(path) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
string startwith = "Nor" + DateTime.Now.ToString("yyyyMMddHHmmss");
if (headers != null && headers.ContentDisposition != null)
{
return headers
.ContentDisposition
.FileName.TrimEnd('"').TrimStart('"').StartsWith("startwith").ToString();
}
return base.GetLocalFileName(headers);
}
This i tried but whatever the original file name that only comes. May I get some idea where can i append datepart to file while saving? Any help would be appreciated. Thank you.
I'm not sure what you're trying to do inside of the GetLocalFileName, this is pretty messed up.
First off, StartsWith returns a boolean (true or false) that indicates if the string starts with whatever you put in the parenthesis.
string str = "SIMPLE";
bool t = str.StartsWith("SIM"); // true
bool f = str.StartsWith("ZIM"); // false
The fact you're turning this bool back into a string and also passing the string "startsWith" into the method, means it will always return the string "false" (a bool value converted into a string) unless the real filename starts with "startsWith".
I think this is what you're looking for:
public override string GetLocalFileName(HttpContentHeaders headers)
{
string prefix = "Nor" + DateTime.Now.ToString("yyyyMMddHHmmss");
if (headers != null && headers.ContentDisposition != null)
{
var filename = headers.ContentDisposition.FileName.Trim('"');
return prefix + filename;
}
return base.GetLocalFileName(headers);
}
My suggestion for you is to learn the basics of C# and .Net a bit more, maybe read a C# book or something.
I am trying to convert this code from C# to VB. Tried to use third party tools, but not successful. Can some one help me .Thanks
private static string RemoveInvalidHtmlTags(this string text)
{
return HtmlTagExpression.Replace(text, new MatchEvaluator((Match m) =>
{
if (!ValidHtmlTags.ContainsKey(m.Groups["tag"].Value))
return String.Empty;
string generatedTag = String.Empty;
System.Text.RegularExpressions.Group tagStart = m.Groups["tag_start"];
System.Text.RegularExpressions.Group tagEnd = m.Groups["tag_end"];
System.Text.RegularExpressions.Group tag = m.Groups["tag"];
System.Text.RegularExpressions.Group tagAttributes = m.Groups["attr"];
generatedTag += (tagStart.Success ? tagStart.Value : "<");
generatedTag += tag.Value;
foreach (Capture attr in tagAttributes.Captures)
{
int indexOfEquals = attr.Value.IndexOf('=');
// don't proceed any futurer if there is no equal sign or just an equal sign
if (indexOfEquals < 1)
continue;
string attrName = attr.Value.Substring(0, indexOfEquals);
// check to see if the attribute name is allowed and write attribute if it is
if (ValidHtmlTags[tag.Value].Contains(attrName))
generatedTag += " " + attr.Value;
}
// add nofollow to all hyperlinks
//if (tagStart.Success && tagStart.Value == "<" && tag.Value.Equals("a", StringComparison.OrdinalIgnoreCase))
// generatedTag += " rel=\"nofollow\"";
if (tag.Value.ToString() == "object")
{
generatedTag += (tagEnd.Success ? " height=\"374\" width=\"416\"" + tagEnd.Value : ">");
}
else
{
generatedTag += (tagEnd.Success ? tagEnd.Value : ">");
}
return generatedTag;
}));
}
The problem converting this code is that you have a lambda expression with a multi-line statement body:
(Match m) =>
{
...a lot of code
}
Since VB9 doesn't support this, you'll want to put the code in brackets into its own function instead:
Private Function GetValue(m As Match) As String
....a lot of code
End Function
Then your RemoveInvalidHtmlTags code will look like this:
Return HtmlTagExpression.Replace(text, new MatchEvaluator(AddressOf GetValue))
You can use free tools to translate the rest of the code.
Have you tried this free tool?