A Simple Helper Class doesn't work - c#

Sorry for asking such a simple question but I lost really long time trying to solve this. At the end, I decide to ask you.
Let's start with the code base :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Navigation.Helpers
{
public static class NavigationBarSE
{
public static MvcHtmlString RenderNavigationBarSE(this HtmlHelper helper, String[] includes)
{
return new MvcHtmlString("Y U no Work??");
//NavTypeSE res = new NavTypeSE(includes);
//String ress = res.toString();
//return new MvcHtmlString(ress);
}
}
}
In the original form, this helper needs to return a String that produced by the NavTypeSE class. But in the end, to get a result, I only want it to return a String for me... But it didn't do that...
Before you ask, I can say that,
<add namespace="Navigation.Helpers"/>
exists in my Web.config file in Views folder.
For detailed information, my NavTypeSE class as below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Navigation.Helpers
{
//Creates a Navigation Menu Type which includes Previous, Next and Validate Buttons
public class NavTypeSE
{
Boolean pr, nt, vld;
Boolean Previous { get; set; }
Boolean Next { get; set; }
Boolean Validate { get; set; }
public NavTypeSE(Boolean Previous, Boolean Next, Boolean Validate)
{
this.pr = Previous;
this.nt = Next;
this.vld = Validate;
}
public NavTypeSE() { }
public NavTypeSE(String[] inc)
{
for(int i=0; i<inc.Length; i++)//foreach (String s in inc)
{
String s = inc[i]; // Don't need for foreach method.
if (s.Equals("previous")||s.Equals("Previous"))
{
this.pr = true;
}
else if (s.Equals("next") || s.Equals("Next"))
{
this.nt = true;
}
else if (s.Equals("validate") || s.Equals("Validate"))
{
this.vld = true;
}
else
{
this.pr = false; this.nt = false; this.vld = false;
}
}
public String toString()
{
return "Previous: " + this.pr + ", Next: " + this.nt + ", Validate: " + this.vld;
}
}
}
Also, in my View, I call this Helper like below :
#{
String[] str = new String[] { "Previous", "next", "Validate" };
Html.RenderNavigationBarSE(str);
}
This is just a base for a project. And I'm starter level in both C# and ASP.NET MVC Platform. Sorry for spending your time.

Your RenderNavigationBarSE writes nothing into the Response just returns a MvcHtmlString.
So you need to put an # before the method call to tell Razor engine that you want to write the returned MvcHtmlString into the response (otherwise inside a code block it just executes your method and throws away the returned value)
#{
String[] str = new String[] { "Previous", "next", "Validate" };
}
#Html.RenderNavigationBarSE(str);
You can read more about the Razor syntax:
Introduction to ASP.NET Web Programming Using the Razor Syntax (C#)
There is also a C# Razor Syntax Quick Reference

Related

How to pass parameters to an api in c#?

I have below api url
http://myapi/api/getproduct?
These parameters will get created from below class
public class ApiParamters
{
public string id {get;set;}
public string name {get;set;}
public List<string> otherNames {get;set;}
}
If value of above parameters are
id=1
name="product1"
OtherNames="oldProduct1" and "oldProduct2"
Then api url should be as below
http://myapi/api/getproduct?id=1&name=product1&OtherNames=oldProduct1&OtherNames=oldProduct2
How to dynamically create these kind of url (GENERIC SOLUTION IS REQUREID because I have to implement simliar logic for other APIs too)
Here's what I came up with using reflection. I'm sure it doesn't handle all the cases, but see if it works for you.
using System.Web;
using System.Reflection;
using System.Collections.Generic;
class Program {
public static string toQueryString(string url, object o)
{
var query = HttpUtility.ParseQueryString(string.Empty);
FieldInfo[] myField = o.GetType().GetFields();
for (int i = 0; i < myField.Length; i++)
{
// Is it a list?
var t = myField[i].GetValue(o) as System.Collections.IEnumerable;
if (t != null)
{
dynamic lst = myField[i].GetValue(o);
int index = 1;
foreach (dynamic oo in lst)
{
query[myField[i].Name + index++] = oo.ToString();
}
}
else
{
query[myField[i].Name] = myField[i].GetValue(o).ToString();
}
}
return query.Count == 0 ? url : url + "?" + query.ToString();
}
}

Roslyn - get grouped single line comments

I am writing a program in C# for extracting comments from code. I am using Roslyn compiler to do that. It's great, because I am just visiting the whole abstract syntax tree and fetching SingleLineComment trivia, MultiLineComment trivia and DocumentationComment trivia syntax from the file in solution. But there is a problem because programmers often write comments like that:
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
You can see that these are three single line comments, but I want them them to be fetched from code as one comment. Can I achieve that with Roslyn or maybe there is another way? Because that's frequent situation when programmers are writing multi line commments using single line comments syntax.
My code for extracting comments looks like this:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
namespace RoslynPlay
{
public class CommentStore
{
public List<Comment> Comments { get; } = new List<Comment>();
public void AddCommentTrivia(SyntaxTrivia trivia,
LocationStore commentLocationstore, string fileName)
{
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia)
{
Comments.Add(new SingleLineComment(trivia.ToString(),
trivia.GetLocation().GetLineSpan().EndLinePosition.Line + 1, commentLocationstore)
{
FileName = fileName,
});
}
else if (trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
{
Comments.Add(new MultiLineComment(trivia.ToString(),
trivia.GetLocation().GetLineSpan().StartLinePosition.Line + 1,
trivia.GetLocation().GetLineSpan().EndLinePosition.Line + 1, commentLocationstore)
{
FileName = fileName,
});
}
}
public void AddCommentNode(DocumentationCommentTriviaSyntax node,
LocationStore commentLocationstore, string fileName)
{
Comments.Add(new DocComment(node.ToString(),
node.GetLocation().GetLineSpan().StartLinePosition.Line + 1,
node.GetLocation().GetLineSpan().EndLinePosition.Line,
commentLocationstore)
{
FileName = fileName,
});
}
}
}
and in main main file (Program.cs) I am launching comment extraction from code like this:
string fileContent;
SyntaxTree tree;
SyntaxNode root;
CommentsWalker commentWalker;
MethodsAndClassesWalker methodWalker;
string[] files = Directory.GetFiles(projectPath, $"*.cs", SearchOption.AllDirectories);
var commentStore = new CommentStore();
Console.WriteLine("Reading files...");
ProgressBar progressBar = new ProgressBar(files.Length);
foreach (var file in files)
{
fileContent = File.ReadAllText(file);
string filePath = new Regex($#"{projectPath}\\(.*)$").Match(file).Groups[1].ToString();
tree = CSharpSyntaxTree.ParseText(fileContent);
root = tree.GetRoot();
commentWalker = new CommentsWalker(filePath, commentStore);
commentWalker.Visit(root);
progressBar.UpdateAndDisplay();
}
and here is also the comment walker:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace RoslynPlay
{
public class CommentsWalker : CSharpSyntaxWalker
{
private string _fileName;
private CommentStore _commentStore;
public CommentsWalker(string fileName,
CommentStore commentStore)
: base(SyntaxWalkerDepth.StructuredTrivia)
{
_fileName = fileName;
_commentStore = commentStore;
}
public override void VisitTrivia(SyntaxTrivia trivia)
{
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia
|| trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
{
_commentStore.AddCommentTrivia(trivia, _commentLocationStore, _fileName);
}
base.VisitTrivia(trivia);
}
public override void VisitDocumentationCommentTrivia(DocumentationCommentTriviaSyntax node)
{
_commentStore.AddCommentNode(node, _commentLocationStore, _fileName);
base.VisitDocumentationCommentTrivia(node);
}
}
}
And the problem is because trivia.Kind() == SyntaxKind.SingleLineCommentTrivia extracts only single line of comments, but I want to extract single line comments blocks as one comment.

C# How to overload the add method with two different strings

I have been trying to build the following Text Adventure and have reached an error that I cannot figure out how to resolve. The error is:
Assets/My_Scripts/MH_Script.cs(19,23): error CS1501: No overload for method Add' takes 2' arguments
Here is the beginning code for MH_Script.cs, the list is rather long since this is a Text Adventure.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MH_Script {
public static List<MH_ScriptManager> sList = new List<MH_ScriptManager>();
public MH_Script(){
sList.Add("start", "You awaken in a sweltering room....
There are more strings added to sList in the same manner followed by:
public string SendScript(string state){
string returnthis = "";
foreach(MH_ScriptManager sm in sList){
if(sm.getState() == state){
returnthis = sm.getStory();
}
}
return returnthis;
}
}
and here is MH_ScriptManager:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MH_ScriptManager{
public Helpers.STATE gState;
public string gScript;
public string getCurrentState(){
return gState;
}
public MH_ScriptManager (string state, string script){
gState = Helpers.ParseEnum<Helpers.STATE>(state);
gScript = script;
}
public string getStory(){
return gScript;
}
public string getState(){
return gState.ToString();
}
public void setStory(string script){
gScript = script;
}
public void setState(string state){
gState = Helpers.ParseEnum<Helpers.STATE>(state);
}
public bool compareStatetoString(string compare){
if (gState == Helpers.ParseEnum<Helpers.STATE> (compare))
return true;
else
return false;
}
}
Can somebody please explain to me what I am doing wrong, and how I can go about resolving this error in the future?
List.Add takes single argument, but in this case you are passing two arguments, which is causing an exception.
Also sList is of type MH_ScriptManager , so what you need is
sList.Add(new MH_ScriptManager("start", "You awaken in a sweltering room..."));
Because Add method should have one argument but you give it two arguments, so
sList.Add("start", "You awaken in a sweltering room);
change to:
sList.Add("You awaken in a sweltering room)

How do I mock a text output from reading a file in C# using the Moq Framework on Monodevelop

I've been banging my head on this all weekend. Basically I am doing a code kata for Game of Life and it involves reading in a text file. I take in that text file which contains two dimensional representation of the grid and stores all the points in a List of List's. I am trying to mock the text input obtained from the file to just be '\n' a new line so I can write unit tests checking that there is a new List being created within the List of Lists. I have created a file wrapper to handle the reading of the text file and that is what I am trying to mock. The code complies fine but the test fails with the error message "System.ArgumentException : The specified path is not of a legal form". It seems to still be expecting a file path but the mocking should change this behaviour right? Any help would be appreciated.
using System.Collections.Generic;
namespace GameOfLife
{
public class InitializeGrid
{
public InitializeGrid ()
{
}
public List<List<char>> CreateCharMatrix (string filePathName)
{
// Reads in the text file containing the grid data
FileWrapper fileWrapper = new FileWrapper ();
string inputGridTextFile = fileWrapper.ReadTextFromFile (filePathName);
// Creates character matrix and initialises the first sub List
List<List<char>> charMatrix = new List<List<char>> ();
charMatrix.Add(new List<char>());
int rowIndex = 0;
int colIndex = 0;
foreach (char cell in inputGridTextFile) {
if (cell == '\n') {
charMatrix.Add (new List<char> ());
rowIndex++;
colIndex = 0;
} else {
charMatrix [rowIndex] [colIndex] = cell;
colIndex++;
}
}
return charMatrix;
}
}
}
using NUnit.Framework;
using System;
using System.Collections.Generic;
using Moq;
namespace GameOfLife
[TestFixture()]
public class InitializeGridTest
{
[Test()]
public void CreateCharMatrix_EnsuresThatWhenEndOfLineReachedNewSubListCreated()
{
//Arrange
InitializeGrid initializeGrid = new InitializeGrid ();
List<List<char>> charMatrix;
string filePathName = " ";
Mock<IFileWrapper> mockFileWrapper = new Mock<IFileWrapper> ();
mockFileWrapper.Setup<string> (m => m.ReadTextFromFile (It.IsAny<string>())).Returns ("\n");
mockFileWrapper.Setup (m => m.ReadTextFromFile (It.IsAny<string>())).Returns ("\n");
//Act
charMatrix = initializeGrid.CreateCharMatrix (filePathName);
int countProvingAnAdditionalListHasBeenAdded = charMatrix.Count;
//Assert
Assert.AreEqual (2, countProvingAnAdditionalListHasBeenAdded);
}
}
using System;
using System.IO;
namespace GameOfLife
{
public class FileWrapper : IFileWrapper
{
public string ReadTextFromFile(string path)
{
return File.ReadAllText (path);
}
}
}
using System;
namespace GameOfLife
{
public interface IFileWrapper
{
string ReadTextFromFile(string filePathName);
}
}
Looking at your code the InitializeGrid is still using the FileWrapper class. It is not using a mocked class so the code is still trying to use the file system.
Your InitializeGrid class needs to use the IFileWrapper interface and not the FileWrapper class. I would look at passing the IFileWrapper interface into the constructor of the InitializeGrid class.
public class InitializeGrid
{
IFileWrapper fileWrapper;
public InitializeGrid (IFileWrapper fileWrapper)
{
this.fileWrapper = fileWrapper;
}
public List<List<char>> CreateCharMatrix (string filePathName)
{
string inputGridTextFile = fileWrapper.ReadTextFromFile (filePathName);
// More code here...
}
}
In your test you would construct the InitializeGrid object using the mocked IFileWrapper by passing the mockFileWrapper.Object to its constructor.
List<List<char>> charMatrix;
string filePathName = " ";
Mock<IFileWrapper> mockFileWrapper = new Mock<IFileWrapper> ();
mockFileWrapper.Setup<string> (m => m.ReadTextFromFile (It.IsAny<string>())).Returns ("\n");
mockFileWrapper.Setup (m => m.ReadTextFromFile (It.IsAny<string>())).Returns ("\n");
InitializeGrid initializeGrid = new InitializeGrid (mockFileWrapper.Object);

3rd party Pdf library significantly slower when running NUnit

I am evaluating Winnovative's PdfToText library and have run into something that concerns me.
Everything runs fine and I am able to extract the text content from a small 20k or less pdf immediately if I am running a console application. However, if I call the same code from the NUnit gui running it takes 15-25 seconds (I've verified it's PdfToText by putting a breakpoint on the line that extracts the text and hitting F10 to see how long it takes to advance to the next line).
This concerns me because I'm not sure where to lay blame since I don't know the cause. Is there a problem with NUnit or PdfToText? All I want to do is extract the text from a pdf, but 20 seconds is completely unreasonable if I'm going to see this behavior under certain conditions. If it's just when running NUnit, that's acceptable, but otherwise I'll have to look elsewhere.
It's easier to demonstrate the problem using a complete VS Solution (2010), so here's the link to make it easier to setup and run (no need to download NUnit or PdfToText or even a sample pdf):
http://dl.dropbox.com/u/273037/PdfToTextProblem.zip (You may have to change the reference to PdfToText to use the x86 dll if you're running on a 32-bit machine).
Just hit F5 and the NUnit Gui runner will load.
I'm not tied to this library, if you have suggestions, I've tried iTextSharp (way too expensive for 2 lines of code), and looked at Aspose (I didn't try it, but the SaaS license is $11k). But they either lack the required functionality or are way too expensive.
(comment turned into answer)
How complex are your PDFs? The 4.1.6 version of iText allows for a closed sourced solution. Although 4.1.6 doesn't directly have a text extractor it isn't too terribly hard to write one using the PdfReader and GetPageContent().
Below is the code I used to extract the text from the PDF using iTextSharp v4.1.6. If it seems overly verbose, it's related to how I'm using it and the flexibility required.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iTextSharp.text.pdf;
namespace ClassLibrary1
{
public class PdfToken
{
private PdfToken(int type, string value)
{
Type = type;
Value = value;
}
public static PdfToken Create(PRTokeniser tokenizer)
{
return new PdfToken(tokenizer.TokenType, tokenizer.StringValue);
}
public int Type { get; private set; }
public string Value { get; private set; }
public bool IsOperand
{
get
{
return Type == PRTokeniser.TK_OTHER;
}
}
}
public class PdfOperation
{
public PdfOperation(PdfToken operationToken, IEnumerable<PdfToken> arguments)
{
Name = operationToken.Value;
Arguments = arguments;
}
public string Name { get; private set; }
public IEnumerable<PdfToken> Arguments { get; private set; }
}
public interface IPdfParsingStrategy
{
void Execute(PdfOperation op);
}
public class PlainTextParsingStrategy : IPdfParsingStrategy
{
StringBuilder text = new StringBuilder();
public PlainTextParsingStrategy()
{
}
public String GetText()
{
return text.ToString();
}
#region IPdfParsingStrategy Members
public void Execute(PdfOperation op)
{
// see Adobe PDF specs for additional operations
switch (op.Name)
{
case "TJ":
PrintText(op);
break;
case "Tm":
SetMatrix(op);
break;
case "Tf":
SetFont(op);
break;
case "S":
PrintSection(op);
break;
case "G":
case "g":
case "rg":
SetColor(op);
break;
}
}
#endregion
bool newSection = false;
private void PrintSection(PdfOperation op)
{
text.AppendLine("------------------------------------------------------------");
newSection = true;
}
private void PrintNewline(PdfOperation op)
{
text.AppendLine();
}
private void PrintText(PdfOperation op)
{
if (newSection)
{
newSection = false;
StringBuilder header = new StringBuilder();
PrintText(op, header);
}
PrintText(op, text);
}
private static void PrintText(PdfOperation op, StringBuilder text)
{
foreach (PdfToken t in op.Arguments)
{
switch (t.Type)
{
case PRTokeniser.TK_STRING:
text.Append(t.Value);
break;
case PRTokeniser.TK_NUMBER:
text.Append(" ");
break;
}
}
}
String lastFont = String.Empty;
String lastFontSize = String.Empty;
private void SetFont(PdfOperation op)
{
var args = op.Arguments.ToList();
string font = args[0].Value;
string size = args[1].Value;
//if (font != lastFont || size != lastFontSize)
// text.AppendLine();
lastFont = font;
lastFontSize = size;
}
String lastX = String.Empty;
String lastY = String.Empty;
private void SetMatrix(PdfOperation op)
{
var args = op.Arguments.ToList();
string x = args[4].Value;
string y = args[5].Value;
if (lastY != y)
text.AppendLine();
else if (lastX != x)
text.Append(" ");
lastX = x;
lastY = y;
}
String lastColor = String.Empty;
private void SetColor(PdfOperation op)
{
lastColor = PrintCommand(op).Replace(" ", "_");
}
private static string PrintCommand(PdfOperation op)
{
StringBuilder text = new StringBuilder();
foreach (PdfToken t in op.Arguments)
text.AppendFormat("{0} ", t.Value);
text.Append(op.Name);
return text.ToString();
}
}
}
And here's how I call it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using iTextSharp.text.pdf;
namespace ClassLibrary1
{
public class PdfExtractor
{
public static string GetText(byte[] pdfBuffer)
{
PlainTextParsingStrategy strategy = new PlainTextParsingStrategy();
ParsePdf(pdfBuffer, strategy);
return strategy.GetText();
}
private static void ParsePdf(byte[] pdf, IPdfParsingStrategy strategy)
{
PdfReader reader = new PdfReader(pdf);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
byte[] page = reader.GetPageContent(i);
if (page != null)
{
PRTokeniser tokenizer = new PRTokeniser(page);
List<PdfToken> parameters = new List<PdfToken>();
while (tokenizer.NextToken())
{
var token = PdfToken.Create(tokenizer);
if (token.IsOperand)
{
strategy.Execute(new PdfOperation(token, parameters));
parameters.Clear();
}
else
{
parameters.Add(token);
}
}
}
}
}
}
}

Categories