List<class> Method exposing WCF service in MVC 4 - wcf

I am working on MVC 4 and WCF Class Library I had added method that is return List and I have added reference of WCF services.
now I am creating proxy of ServiceReference1 then I am not able to get this ServiceReference1 object.
if I changed return type to string then it working..
I had tried changing all collection type but I dint get ServiceReference1 object.!
where I am wrong or what is the solution.?
My WCF code is here
public class BuildTrackerService : IBuildTrackerService
{
public List<Property> DoWork()
{
DataTable dt = new DataTable();
List<Property> objProperty = new List<Property>();
SqlConnection conn = DbConnection.GetConnection();
SqlDataAdapter adpt = new SqlDataAdapter("[GetPropertyDetail]", conn);
adpt.SelectCommand.CommandType = CommandType.StoredProcedure;
try
{
conn.Open();
adpt.Fill(dt);
}
catch (Exception) { throw; }
finally
{
conn.Close();
adpt.Dispose();
}
objProperty = DataTableHelper.ConvertTo<Property>(dt);
return objProperty;
}
}
MY MVC 4 ActionResult is like
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
/*
==> this ServiceReference1 is not accessible here....!
var obj = new ServiceReference1.BuildTrackerServiceClient();
*/
var objct = obj.DoWork();
return View();
}
I had tried with !

With a WCF web service you can transport only primitive types. Changes your list to an array and try it again.

Related

wcf web service only generates async methods when consuming it in xamarin.forms app

i am trying to connect my xamarin.forms app to sql server. i know that i have to use a webservice to do that. i am using wcf web service. the problem is that i only got async methods after adding it as a connected service to my app. like the problem in this question: Xamarin.Forms Add Connected Service on WCF only generated async method the thing is i can't use its answer because i don't have the generate synchronous operations option, i found another answer in this: WCFclient operation only Async .Net core 2.0 but i really still don't know how to use the async methods. like how do i get the result of the operation to perform my login when clicking a button. this is my code for the wcf webservice:
Iuserlogin.cs:
[ServiceContract]
public interface Iuserlogin
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, Method = "POST")]
DataTable login(string username, string pass);
}
userlogin.svc.cs:
public class userlogin : Iuserlogin
{
public DataTable login(string username, string pass)
{
DataTable dt = new DataTable();
dt.TableName = "summary_req";
SqlConnection con = new SqlConnection("server=DESKTOP-CPOJ94O\\MSSQLSERVER1;database=users;integrated security=true");
con.Open();
SqlCommand cmd = new SqlCommand("SELECT username, password FROM hjk where CONVERT(VARCHAR, username)=#username and CONVERT(VARCHAR, password)=#password", con);
cmd.Parameters.AddWithValue("#username", username);
cmd.Parameters.AddWithValue("#password", pass);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
return dt;
}
}
}
this is my trial to use the async functions in my app:
MainPage.xaml.cs:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void SignIn_Clicked(object sender, EventArgs e)
{
ServiceReference1.IuserloginClient cs = new ServiceReference1.IuserloginClient();
string user_name = username.Text;
string pass = password.Text;
ServiceReference1.loginRequest loginreq= new ServiceReference1.loginRequest(user_name, pass);
ServiceReference1.loginResponse response = cs.loginAsync(user_name, pass).Result;
}
}
}
i don't know what to do next. how do i continue to know if the user can login or not. how do i get a datatable result from the wcf functions.
thanks in advance.

IRazorViewEngine.FindView with GetView can't find view

In my asp.net core project I'm trying to find Razor view using this method:
private IView FindView(ActionContext actionContext, string viewName)
{
var getViewResult = _viewEngine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true);
if (getViewResult.Success)
{
return getViewResult.View;
}
var findViewResult = _viewEngine.FindView(actionContext, viewName, isMainPage: true);
if (findViewResult.Success)
{
return findViewResult.View;
}
var searchedLocations = getViewResult.SearchedLocations.Concat(findViewResult.SearchedLocations);
var errorMessage = string.Join(
Environment.NewLine,
new[] { $"Unable to find view '{viewName}'. The following locations were searched:" }.Concat(searchedLocations));
throw new InvalidOperationException(errorMessage);
}
where
viewName = "Views/Email/ResetPassword.cshtml"
and _viewEngine is IRazorViewEngine, but it doesn't find any.
My project structure:
IView.FindView method is called from Business.
I also have another project, that have the project structure and uses the same method for retrieving views and, more importantly, it finds this view, but it uses netcoreapp2.2, and my current project uses netcoreapp3.1 (Microsoft.AspNetCore.Mvc.Razor versions are the same - 2.2.0).
Why can't this method find views on .net core 3.1?
UPDATE
Both projects copy this Views folder to Api\bin\Debug\netcoreapp{version} folder on build.
Though I was building things from scratch in Core 3.1 and not upgrading from an earlier version, I ran into the same issue. I got things working by the doing the following:
I created an implementation of IWebHostEnvironment (I called mine DummyWebHostEnvironment.cs). I left all but one of the interface's properties with the default implementation; for that one property, I used the name of the project containing the views. (I just hardcoded it into the sample below for brevity; there are obviously slicker ways to obtain it.)
public class DummyWebHostEnvironment : IWebHostEnvironment
{
public IFileProvider WebRootFileProvider { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
public string WebRootPath { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
public string ApplicationName { get => "TheProjectContainingMyViews.RazorClassLibrary"; set => throw new System.NotImplementedException(); }
public IFileProvider ContentRootFileProvider { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
public string ContentRootPath { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
public string EnvironmentName { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
}
Note: As is evident from the above code, the project containing the Views is a RazorClassLibrary. (I was using this and this as guidesfor getting the RazorViewEngine to work in a console application.)
One I had the implementation above, I added it to my services collection along with some other goodies:
private static RazorViewToStringRenderer GetRenderer()
{
var services = new ServiceCollection();
var applicationEnvironment = PlatformServices.Default.Application;
services.AddSingleton(applicationEnvironment);
var appDirectory = Directory.GetCurrentDirectory();
var environment = new DummyWebHostEnvironment();
services.AddSingleton<IWebHostEnvironment>(environment);
services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
services.AddSingleton<DiagnosticSource>(diagnosticSource);
services.AddSingleton<DiagnosticListener>(diagnosticSource);
services.AddLogging();
services.AddMvc();
services.AddSingleton<RazorViewToStringRenderer>();
var provider = services.BuildServiceProvider();
return provider.GetRequiredService<RazorViewToStringRenderer>();
}
Note: See the first of the links above for the code for RazorViewToStringRenderer. Here's the interface:
public interface IRazorViewToStringRenderer
{
Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model);
}
Then, in Program.cs, I can just do something like this:
static async Task Main(string[] args)
{
var dto = BuildDto();
var renderer = GetRenderer();
var renderedString = await renderer.RenderViewToStringAsync("Views/Path/To/Some.cshtml", dto);
// ...
}
I had the same issue. Although I am writing in .NET Core 5 already.
I am assuming you are writing based on this or similar solution: https://scottsauber.com/2018/07/07/walkthrough-creating-an-html-email-template-with-razor-and-razor-class-libraries-and-rendering-it-from-a-net-standard-class-library/
You have
var getViewResult = _viewEngine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true);
where executingFilePath is null.
Add executingFilePath so it leads to the view location on disk.
In my solution I have:
var getViewResult = _viewEngine.GetView(executingFilePath: executingFilePath, viewPath: viewName, isMainPage: true);
where executingFilePath is passed to RenderViewToStringAsync as additional parameter:
public class MessageBodyBuilderService : IMessageBodyBuilderService
{
private readonly IRazorViewToStringRenderer _razorViewToStringRenderer;
private readonly IWebHostEnvironment _hostingEnv;
private readonly string _pathToEmailTemplates = $"/Views/EmailTemplates/";
public MessageBodyBuilderService(
IWebHostEnvironment hostingEnv,
IRazorViewToStringRenderer razorViewToStringRenderer)
{
_hostingEnv = hostingEnv;
_razorViewToStringRenderer = razorViewToStringRenderer;
}
public async Task<BodyBuilder> BuildMessage<T>(string templateName, T modelForReplacement, bool isHtml = true)
{
string viewName = $"{_pathToEmailTemplates}{templateName}.cshtml";
string body = await _razorViewToStringRenderer.RenderViewToStringAsync(viewName, modelForReplacement, _hostingEnv.ContentRootPath);
var builder = new BodyBuilder()
{
HtmlBody = body
};
return builder;
}
}
where _hostingEnv.ContentRootPath comes from the ContentRootPath I declared on Startup:
AppDomain.CurrentDomain.SetData("ContentRootPath", webHostEnvironment.ContentRootPath);
and then you can pass executingFilePath (in your RazorViewToStringRenderer's RenderViewToStringAsync method) to FindView as additional parameter:
var view = FindView(executingFilePath, actionContext, viewName);
I hope it helps.

How to create single instance for multiple endpopints in wcf

Scenario:
I have single instance type of wcf service. which keep data in memory.
Clients call the service and get data without hitting the db.
Wcf Service is host in windows service.
In windows service i have used timer, on the bases of which wcf service hit the database and refresh the data.
Now problem is that when call of refresh take place, request of data client impacted and got time out.
Now i have tried two endpoints. One for consumer and second for refresh.
Both working well, but even refresh endpoint refresh the data. consumer endpoint gives old data whether refresh endpoint showing correct data.
Code Example
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service1 : IService1
{
List<string> Name;
public Service1()
{
Name = new List<string>();
CollectData1();
}
public List<string> CollectData()
{
CollectData1();
return Name;
}
public List<string> CollectData1()
{
List<string> _name = new List<string>();
string connectionString = ConfigurationManager.ConnectionStrings["DBConnectionString"].ConnectionString;
using (SqlConnection sqlConnection1 = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "select name from test";
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
string a = Convert.ToString(reader[0]);
_name.Add(a);
}
}
}
}
}
Name = _name;
return Name;
}
public List<string> GetData()
{
return Name;
}
}

how to call wcf service asynchronously from MVC4's controller

I created a project that have WCF service and client consume it asynchronously
(like the one in http://msdn.microsoft.com/en-us/library/bb885132.aspx)
The problem comes with me if the client is MVC4
When I call the wcf from client-side, the code is
ChannelFactory<IMathService> myChannelFactory =
new ChannelFactory<IMathService>(myBinding, myEndpoint);
myChannelFactory.Open();
IMathService instance = myChannelFactory.CreateChannel();
// Call Service.
IAsyncResult ar = instance.BeginFunction(param,
(are) =>
{
result = ((IMathService)are.AsyncState).EndFunction(are);
}
, instance);
return View(result);
With this code, my "result" is always default value.
How can I make the action wait until the result has value from EndFunction?
Thanks
You need to use ASP .NET MVC AsyncController
Full explanation - http://msdn.microsoft.com/en-us/library/ee728598(v=vs.98).aspx
Edited sample for your scenario-
public class PortalController : AsyncController {
public void NewsAsync(string city) {
AsyncManager.OutstandingOperations.Increment();
ChannelFactory<IMathService> myChannelFactory =
new ChannelFactory<IMathService>(myBinding, myEndpoint);
myChannelFactory.Open();
IMathService instance = myChannelFactory.CreateChannel();
// Call Service.
IAsyncResult ar = instance.BeginFunction(param,
(are) =>
{
AsyncManager.Parameters["result"] = ((IMathService)are.AsyncState).EndFunction(are);
AsyncManager.OutstandingOperations.Decrement();
}
, instance);
}
public ActionResult NewsCompleted(string[] result) {
return View(result);
}
}

How can I add datacontract to a type (xxxDataTable) which is created by a typed data set?

I have a typed data set and I want to pass tables(which are created by .net) or collection of rows instead of objects(which I would be creating) or collecion of objects to the client side. Silverlight framework doesn't support system.data.datatable.
you don't need to add datacontract attribute to types you don't own. You can implement IDataContractSurrogate to replace instances of client-unknown types with known-type instances (for example lightweight datatable POCO).
If you used code-first approach, you wouldn't have this extra projection-copy operation between typed dataset class objects and your own POCO objects on serialization/deserialization (and you would have full control over data object types (POCOs)).
I find useful to use Json.Net 'any object to JObject' convertor (pretty fast and customizable) as first step before converting to something else:
public static class JsonExtensions
{
public static object Normalize(this JToken token)
{
var type = token.GetType();
if (type == typeof(JObject))
{
return (token as JObject).OfType<JProperty>().ToDictionary<JProperty, string, object>(property => property.Name, property => property.Value.Normalize());
}
if (type == typeof(JProperty))
{
var property = token as JProperty;
//return new DictionaryEntry(property.Name, property.Value.Normalize());
return new KeyValuePair<string, object>(property.Name, property.Value.Normalize());
}
if (type == typeof(JValue))
{
return (token as JValue).Value;
}
if (type == typeof(JArray))
{
//return (token as JArray).OfType<JValue>().Select(value => value.Normalize()).ToArray();
return (token as JArray).Select(value => value.Normalize()).ToArray();
}
throw new NotImplementedException();
//return null;
}
}
public class TestClass
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
public TestClass RefProperty { get; set; }
}
private static string DataContractXmlSerialize<T>(T source)
{
var serializer = new DataContractSerializer(source.GetType());
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, source);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
Usage:
var test = new TestClass()
{
StringProperty = "StringProperty",
IntProperty = int.MaxValue,
RefProperty = new TestClass() { IntProperty = int.MinValue }
};
var jObj = JObject.FromObject(test);
var dict = jObj.Normalize();
var serializedDict = DataContractXmlSerialize(dict);
as you can see - output is WCF-serializable (standard dictionary being serialized produces not very nice xml with but you can use your own serializable dictionary)
You simply cannot use the ADO.NET implementation of a DataTable in your Silverlight client, but there are alternatives.
However, this blog post has an alternative DataTable implementation that you can serialize and can support in Silverlight.
If you want to access data in Silverlight application you should use RIA Services. You should create custom DTO object and create list of DTO objects from your DataTable rows and return it from RIA Service.
You get started with RIA Services follow MSDN at http://msdn.microsoft.com/en-us/library/ee707376(v=vs.91).aspx